• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Django:Admin,Cookie,Session

    一. Admin的配置

    1.Admin基礎設置

      admin是django強大功能之一,它能夠從數據庫中讀取數據,呈現在頁面中,進行管理。默認情況下,它的功能已經非常強大,如果你不需要復雜的功能,它已經夠用,但是有時候,一些特殊的功能還需要定制,比如搜索功能,下面這一系列文章就逐步深入介紹如何定制適合自己的admin應用。

    <1> 在settings中設置Admin界面顯示語言

    LANGUAGE_CODE = 'en-us'  #LANGUAGE_CODE = 'zh-hans'

    <2> 認識ModelAdmin,管理界面的定制類,如需擴展特定的model界面需從該類繼承。

    <3>注冊model類到admin的兩種方式:

         1)   使用register的方法

    admin.site.register(Book,MyAdmin)

         2)  使用register的裝飾器

    @admin.register(Book)

    <4>掌握一些常用的設置技巧

       list_display:指定要顯示的字段

       search_fields:指定搜索的字段

       list_filter:指定列表過濾器

       ordering:指定排序字段

     list_per_page:設置每頁顯示多少條記錄,默認是100條

     list_editable:設置默認可編輯字段

     fk_fields: 設置顯示外鍵字段

     date_hierarchy:按Admin自制表中的時間字段過濾

    from django.contrib import admin
    from ORM_Study.models import *
    
    # Register your models here.
    # @admin.register(book)#----->單給某個表加一個定制
    class MyAdmin(admin.ModelAdmin):
        list_display = ("title", "price","publish")
        search_fields = ("title","publish__name")
        list_filter = ("publish",)
        ordering = ("price",)
        list_per_page = 3
        date_hierarchy ="date"
    admin.site.register(book,MyAdmin)
    View Code

    <5>Admin常用設置詳解

    在admin.py中只需要講Mode中的某個類注冊,即可在Admin中實現增刪改查的功能,如:

    admin.site.register(models.UserInfo)

    但是,這種方式比較簡單,如果想要進行更多的定制操作,需要利用ModelAdmin進行操作,如:

    復制代碼
    方式一:
        class UserAdmin(admin.ModelAdmin):
            list_display = ('user', 'pwd',)
     
        admin.site.register(models.UserInfo, UserAdmin) # 第一個參數可以是列表
         
     
    方式二:
        @admin.register(models.UserInfo)                # 第一個參數可以是列表
        class UserAdmin(admin.ModelAdmin):
            list_display = ('user', 'pwd',)
    復制代碼

    ModelAdmin中提供了大量的可定制功能,如

     1. list_display,列表時,定制顯示的列。

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        list_display = ('user', 'pwd', 'xxxxx')
     
        def xxxxx(self, obj):
            return "xxxxx"

    2. list_display_links,列表時,定制列可以點擊跳轉。

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        list_display = ('user', 'pwd', 'xxxxx')
        list_display_links = ('pwd',)

    3. list_filter,列表時,定制右側快速篩選。

    4. list_select_related,列表時,連表查詢是否自動select_related

    5. list_editable,列表時,可以編輯的列 

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        list_display = ('user', 'pwd','ug',)
        list_editable = ('ug',)

    6. search_fields,列表時,模糊搜索的功能

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
         
        search_fields = ('user', 'pwd')

    7. date_hierarchy,列表時,對Date和DateTime類型進行搜索

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
     
        date_hierarchy = 'ctime'

    8  inlines,詳細頁面,如果有其他表和當前表做FK,那么詳細頁面可以進行動態增加和刪除

    復制代碼
    class UserInfoInline(admin.StackedInline): # TabularInline
        extra = 0
        model = models.UserInfo
     
     
    class GroupAdminMode(admin.ModelAdmin):
        list_display = ('id', 'title',)
        inlines = [UserInfoInline, ]
    復制代碼

    9 action,列表時,定制action中的操作

    復制代碼
    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
     
        # 定制Action行為具體方法
        def func(self, request, queryset):
            print(self, request, queryset)
            print(request.POST.getlist('_selected_action'))
     
        func.short_description = "中文顯示自定義Actions"
        actions = [func, ]
     
        # Action選項都是在頁面上方顯示
        actions_on_top = True
        # Action選項都是在頁面下方顯示
        actions_on_bottom = False
     
        # 是否顯示選擇個數
        actions_selection_counter = True
    復制代碼

    10 定制HTML模板

    add_form_template = None
    change_form_template = None
    change_list_template = None
    delete_confirmation_template = None
    delete_selected_confirmation_template = None
    object_history_template = None

    11 raw_id_fields,詳細頁面,針對FK和M2M字段變成以Input框形式

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
     
        raw_id_fields = ('FK字段', 'M2M字段',)

    12  fields,詳細頁面時,顯示字段的字段

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        fields = ('user',)

    13 exclude,詳細頁面時,排除的字段

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        exclude = ('user',)

    14  readonly_fields,詳細頁面時,只讀字段

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        readonly_fields = ('user',)

    15 fieldsets,詳細頁面時,使用fieldsets標簽對數據進行分割顯示

    復制代碼
    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        fieldsets = (
            ('基本數據', {
                'fields': ('user', 'pwd', 'ctime',)
            }),
            ('其他', {
                'classes': ('collapse', 'wide', 'extrapretty'),  # 'collapse','wide', 'extrapretty'
                'fields': ('user', 'pwd'),
            }),
        )
    復制代碼

    16 詳細頁面時,M2M顯示時,數據移動選擇(方向:上下和左右)

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)

    17 ordering,列表時,數據排序規則

    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        ordering = ('-id',)
        或
        def get_ordering(self, request):
            return ['-id', ]

    18. radio_fields,詳細頁面時,使用radio顯示選項(FK默認使用select)

    radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL

    19 form = ModelForm,用于定制用戶請求時候表單驗證

    復制代碼
    from app01 import models
    from django.forms import ModelForm
    from django.forms import fields
     
     
    class MyForm(ModelForm):
        others = fields.CharField()
     
        class Meta:
            model = models = models.UserInfo
            fields = "__all__"
     
    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
     
        form = MyForm
    復制代碼

    20 empty_value_display = "列數據為空時,顯示默認值"

    復制代碼
    @admin.register(models.UserInfo)
    class UserAdmin(admin.ModelAdmin):
        empty_value_display = "列數據為空時,默認顯示"
     
        list_display = ('user','pwd','up')
     
        def up(self,obj):
            return obj.user
        up.empty_value_display = "指定列數據為空時,默認顯示"
    復制代碼

     

    二. Cookie和Session

    1.Cookie和Session的基本介紹 

      cookie不屬于http協議范圍,由于http協議無法保持狀態,但實際情況,我們卻又需要“保持狀態”,因此cookie就是在這樣一個場景下誕生。cookie的工作原理是:由服務器產生cookie內容,瀏覽器收到請求響應后保存在本地;當瀏覽器再次訪問該服務器時,瀏覽器會自動帶上cookie,這樣服務器就能通過cookie的內容來判斷這個是“誰”。簡明來說,基于http協議的無狀態特征,服務器根本就不知道訪問者是“誰”,那么上述的cookie就起到橋接的作用,我們可以給每個客戶端的cookie分配一個唯一的id,這樣用戶在訪問時,通過cookie,服務器就知道來的人是“誰”,然后我們再根據不同的cookie的id,在服務器上保存一段時間的私密資料,如“賬號密碼”等等。cookie雖然在一定程度上解決了“保持狀態”的需求,但是由于cookie本身最大支持4096字節,以及cookie本身保存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支持更多的字節,并且他保存在服務器,有較高的安全性,這便出現了session。

    cookie的格式:

    Set-Cookie: NAME=VALUE;Expires/Max-age=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE

    參數意義:

    • NAME:cookie的名字。
    • VALUE:cookie的值。
    • Expires:cookie的過期時間。
    • Path:cookie作用的路徑。
    • Domain:cookie作用的域名。
    • SECURE:是否只在https協議下起作用。

      總結:cookie彌補了http無狀態的不足,讓服務器知道來的人是“誰”;但是cookie以文本的形式保存在本地,自身安全性較差;所以我們就通過cookie識別不同的用戶,對應的在session里保存私密的信息以及超過4096字節的文本。

      經過前面的學習我們已經有能力制作一個登陸頁面,在驗證了用戶名和密碼的正確性后跳轉到后臺的頁面。但是測試后也發現,如果繞過登陸頁面,直接輸入后臺的url地址也可以直接訪問。這個顯然是不合理的。其實我們缺失的就是cookie和session配合的驗證。有了這個驗證過程,我們就可以實現和其他網站一樣必須登錄才能進入后臺頁面了。

          先說一下這種認證的機制。每當我們使用一款瀏覽器訪問一個登陸頁面的時候,一旦我們通過了認證。服務器端就會發送一組隨機唯一的字符串(假設是123abc)到瀏覽器端,這個被存儲在瀏覽器端的東西就叫cookie。而服務器端也會自己存儲一下用戶當前的狀態,比如login=true,username=hahaha之類的用戶信息。但是這種存儲是以字典形式存儲的,字典的唯一key就是剛才發給用戶的唯一的cookie值。那么如果在服務器端查看session信息的話,理論上就會看到如下樣子的字典

    {'123abc':{'login':true,'username:hahaha'}}

      因為每個cookie都是唯一的,所以我們在電腦上換個瀏覽器再登陸同一個網站也需要再次驗證。那么為什么說我們只是理論上看到這樣子的字典呢?因為處于安全性的考慮,其實對于上面那個大字典不光key值123abc是被加密的,value值{'login':true,'username:hahaha'}在服務器端也是一樣被加密的。所以我們服務器上就算打開session信息看到的也是類似與以下樣子的東西{'123abc':dasdasdasd1231231da1231231}

    借用一張別的大神畫的圖,可以更直觀的看出來cookie和session的關系

      

     

    cookie和session的應用實例:

    <1>先在templates目錄下創建兩個html,login.html負責登錄頁面,backend頁面代表后臺頁面

    /*---------------------------login.html-----------------------------*/
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
         <div class="container">
            <form action="login.html" method="post">
                <div class="form-group">
                    <label class="sr-only">username</label>
                    <input type="text" class="form-control" name="username" placeholder="用戶名"/>
                </div>
                <div class="form-group">
                    <label class="sr-only">Password</label>
                    <input type="password" class="form-control" name="passwd" placeholder="密碼"/>
                </div>
                <div class="form-group">
                    <input class="btn btn-primary" type="submit" value="提交">
                </div>
            </form>
    </div>
    </body>
    </html>
    
    /*---------------------------backend.html-----------------------*/
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div class="container">
        <h2>cookie 內容是 {{ cookie_content }}</h2>
        <h2>session 內容是 {{ session_content }}</h2>
        <h2>登錄用戶名 :{{ username }}</h2>
       </div>
    </body>
    </html>
    View Code

    <2> 在應用下的views.py文件,編寫代碼邏輯部分

    def login(request):
        print("COOKIES", request.COOKIES)
        print("SESSION", request.session)
        #------------首次進入login.html頁面cookies和session打印內容
        #COOKIES {'csrftoken': 'x8OVNJyVE7SMVgPXTLSoJiNNr6KSTG7CyOwXHoKhBKsFwlCyCXh3UVfHExheoA0g', 'sessionid': '9s3jx5sb5euzdla2d1aq44yrehvun1e2'}
        #SESSION <django.contrib.sessions.backends.db.SessionStore object at 0x00000213ADA15DA0>
    
        if request.method == "POST":
            username = request.POST['username']
            pwd = request.POST['passwd']
            print('================================')
    
            if username == 'abc' and pwd == '123':
                #----------------cookie單獨使用---------------------
                #cookie單獨使用時,設置cookiea內部字典的內容
                # ret=redirect('/backend/')
                # ret.set_cookie("username",username)
                # return ret
    
                #----------cookie和sessions結合使用-----------------
                # 設置session內部的字典內容
                request.session['is_login'] = 'true'
                request.session['username'] = 'abc'
                #登錄成功就將url重定向到后臺的url
                return redirect('/backend/')
            # 登錄不成功或第一訪問就停留在登錄頁面
        return render(request,'login.html')
    
    def backend(request):
        print("COOKIES", request.COOKIES)
        print("SESSION", request.session)
        #-----------------------cookie單獨使用------------------
        # if request.COOKIES.get("username", None):
        #     username = request.COOKIES.get("username", None)
        #     cookie_content = request.COOKIES
        #     return render(request, "backend.html", locals())
        #     #返回值:
        #     # cookie內容是{'username': 'abc'}
        #     # session 內容是
        #     # 登錄用戶名 :abc
    
        #-----------------cookie和session結合使用-----------------
        """
            這里必須用讀取字典的get()方法把is_login的value缺省設置為False,
            當用戶訪問backend這個url先嘗試獲取這個瀏覽器對應的session中的
            is_login的值。如果對方登錄成功的話,在login里就已經把is_login
            的值修改為了True,反之這個值就是False的
            """
        is_login = request.session.get('is_login', False)
        # 如果為真,就說明用戶是正常登陸的
        if is_login:
            # 獲取字典的內容并傳入頁面文件
            # 或者用if request.session.get("is_login",None):
            cookie_content = request.COOKIES
            session_content = request.session
            username = request.session['username']
            return render(request, 'backend.html',
                          {
                              'cookie_content': cookie_content,
                              'session_content': session_content,
                              'username': username
                          })
            #返回的值:
            # cookie 內容是 {'csrftoken': 'x8OVNJyVE7SMVgPXTLSoJiNNr6KSTG7CyOwXHoKhBKsFwlCyCXh3UVfHExheoA0g', 'sessionid': '9s3jx5sb5euzdla2d1aq44yrehvun1e2'}
            # session內容是 < django.contrib.sessions.backends.db.SessionStore object at 0x000001BF7D04DDD8 >
            # 登錄用戶名 :abc
        else:
            """
            如果訪問的時候沒有攜帶正確的session,
            就直接被重定向url回login頁面
            """
        return redirect('/login/')
    View Code

    <3>編輯urls.py文件,設置函數與頁面的綁定關系

    from django.contrib import admin
    from django.urls import path
    from ORM_Study import views
    from django.conf.urls import url
    
    urlpatterns = [
        #path('admin/', admin.site.urls),
        url('^login/',views.login,name='login'),
        url('^backend/',views.backend,name='backend'),
    ]
    View Code

    <4>最后打開瀏覽器直接訪問/backend/頁面,檢測是否直接就被重定向到了/login/頁面

    <5>總結 

      從上述步驟中我們看到有一下幾點:

      (1)login頁面正確登錄的話,后臺頁面可以獲取到瀏覽器攜帶的cookie的。

      (2)返回的sessionid其實就是cookie值

      (3)session的內容是加密的,從客戶端獲取不到session的內容

      (4)服務端可以通過預設的key值取出session的內容并打印到前段

      (5)django的session默認是存儲在數據庫里的,我們可以到數據庫查看一下真正session內容,在表Django_session里

      (6)session的好處:客戶端只有cookie值,始終沒有用戶信息

      (7)session依賴于cookie,cookie保存在瀏覽器,session保存在服務器端。

    <6>cookie和session的知識點總結:

     操作cookie:  

    獲取cookie:request.COOKIES[key]
    
    設置cookie:response.set_cookie(key,value)
    View Code

     操作session(session默認在服務器端保存15天):

    獲取session:request.session[key]
    
    設置session:reqeust.session[key] = value
    
    刪除session:del request.session[key]    
    
    設置session時效: request.session.set_expiry(value)
    * 如果value是個整數,session會在這些秒數后失效。
    * 如果value是個datatime或timedelta,session就會在這個時間后失效。
    * 如果value是0,用戶關閉瀏覽器session就會失效。
    * 如果value是None,session會依賴全局session失效策略。
    View Code

     >>>>>>>>>待續

    版權聲明:本文為weixin_33898233原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/weixin_33898233/article/details/93219077

    智能推薦

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    猜你喜歡

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    19.vue中封裝echarts組件

    19.vue中封裝echarts組件 1.效果圖 2.echarts組件 3.使用組件 按照組件格式整理好數據格式 傳入組件 home.vue 4.接口返回數據格式...

    劍指Offer39-調整數組順序使奇數位于偶數前面

    一開始想著用冒泡排序的方法來做,但是bug還是很多,后來看了評論區答案,發現直接空間換時間是最簡單的,而且和快排的寫法是類似的。...

    精品国产乱码久久久久久蜜桃不卡