Django:Admin,Cookie,Session
一. Admin的配置
1.Admin基礎(chǔ)設(shè)置
admin是django強(qiáng)大功能之一,它能夠從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),呈現(xiàn)在頁(yè)面中,進(jìn)行管理。默認(rèn)情況下,它的功能已經(jīng)非常強(qiáng)大,如果你不需要復(fù)雜的功能,它已經(jīng)夠用,但是有時(shí)候,一些特殊的功能還需要定制,比如搜索功能,下面這一系列文章就逐步深入介紹如何定制適合自己的admin應(yīng)用。
<1> 在settings中設(shè)置Admin界面顯示語(yǔ)言
LANGUAGE_CODE = 'en-us' #LANGUAGE_CODE = 'zh-hans'<2>?認(rèn)識(shí)ModelAdmin,管理界面的定制類,如需擴(kuò)展特定的model界面需從該類繼承。
<3>注冊(cè)model類到admin的兩種方式:
? ? ?1)? ?使用register的方法
admin.site.register(Book,MyAdmin)? ? ?2)? 使用register的裝飾器
@admin.register(Book)<4>掌握一些常用的設(shè)置技巧
? ?list_display:指定要顯示的字段
? ?search_fields:指定搜索的字段
? ?list_filter:指定列表過濾器
? ?ordering:指定排序字段
list_per_page:設(shè)置每頁(yè)顯示多少條記錄,默認(rèn)是100條
list_editable:設(shè)置默認(rèn)可編輯字段
fk_fields: 設(shè)置顯示外鍵字段
date_hierarchy:按Admin自制表中的時(shí)間字段過濾
from django.contrib import admin from ORM_Study.models import *# Register your models here. # @admin.register(book)#----->單給某個(gè)表加一個(gè)定制 class MyAdmin(admin.ModelAdmin):list_display = ("title", "price","publish")search_fields = ("title","publish__name")list_filter = ("publish",)ordering = ("price",)list_per_page = 3date_hierarchy ="date" admin.site.register(book,MyAdmin) View Code<5>Admin常用設(shè)置詳解
在admin.py中只需要講Mode中的某個(gè)類注冊(cè),即可在Admin中實(shí)現(xiàn)增刪改查的功能,如:
admin.site.register(models.UserInfo)但是,這種方式比較簡(jiǎn)單,如果想要進(jìn)行更多的定制操作,需要利用ModelAdmin進(jìn)行操作,如:
方式一:class UserAdmin(admin.ModelAdmin):list_display = ('user', 'pwd',)admin.site.register(models.UserInfo, UserAdmin) # 第一個(gè)參數(shù)可以是列表方式二:@admin.register(models.UserInfo) # 第一個(gè)參數(shù)可以是列表class UserAdmin(admin.ModelAdmin):list_display = ('user', 'pwd',)ModelAdmin中提供了大量的可定制功能,如
?1.?list_display,列表時(shí),定制顯示的列。
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):list_display = ('user', 'pwd', 'xxxxx')def xxxxx(self, obj):return "xxxxx"2.?list_display_links,列表時(shí),定制列可以點(diǎn)擊跳轉(zhuǎn)。
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):list_display = ('user', 'pwd', 'xxxxx')list_display_links = ('pwd',)3.?list_filter,列表時(shí),定制右側(cè)快速篩選。
4.?list_select_related,列表時(shí),連表查詢是否自動(dòng)select_related
5. list_editable,列表時(shí),可以編輯的列?
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):list_display = ('user', 'pwd','ug',)list_editable = ('ug',)6.?search_fields,列表時(shí),模糊搜索的功能
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):search_fields = ('user', 'pwd')7.?date_hierarchy,列表時(shí),對(duì)Date和DateTime類型進(jìn)行搜索
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):date_hierarchy = 'ctime'8??inlines,詳細(xì)頁(yè)面,如果有其他表和當(dāng)前表做FK,那么詳細(xì)頁(yè)面可以進(jìn)行動(dòng)態(tài)增加和刪除
class UserInfoInline(admin.StackedInline): # TabularInlineextra = 0model = models.UserInfoclass GroupAdminMode(admin.ModelAdmin):list_display = ('id', 'title',)inlines = [UserInfoInline, ]9 action,列表時(shí),定制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選項(xiàng)都是在頁(yè)面上方顯示actions_on_top = True# Action選項(xiàng)都是在頁(yè)面下方顯示actions_on_bottom = False# 是否顯示選擇個(gè)數(shù)actions_selection_counter = True10 定制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 = None11 raw_id_fields,詳細(xì)頁(yè)面,針對(duì)FK和M2M字段變成以Input框形式
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):raw_id_fields = ('FK字段', 'M2M字段',)12??fields,詳細(xì)頁(yè)面時(shí),顯示字段的字段
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):fields = ('user',)13?exclude,詳細(xì)頁(yè)面時(shí),排除的字段
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):exclude = ('user',)14??readonly_fields,詳細(xì)頁(yè)面時(shí),只讀字段
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):readonly_fields = ('user',)15?fieldsets,詳細(xì)頁(yè)面時(shí),使用fieldsets標(biāo)簽對(duì)數(shù)據(jù)進(jìn)行分割顯示
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):fieldsets = (('基本數(shù)據(jù)', {'fields': ('user', 'pwd', 'ctime',)}),('其他', {'classes': ('collapse', 'wide', 'extrapretty'), # 'collapse','wide', 'extrapretty''fields': ('user', 'pwd'),}),)16 詳細(xì)頁(yè)面時(shí),M2M顯示時(shí),數(shù)據(jù)移動(dòng)選擇(方向:上下和左右)
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)17 ordering,列表時(shí),數(shù)據(jù)排序規(guī)則
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):ordering = ('-id',)或def get_ordering(self, request):return ['-id', ]18.?radio_fields,詳細(xì)頁(yè)面時(shí),使用radio顯示選項(xiàng)(FK默認(rèn)使用select)
radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL19?form = ModelForm,用于定制用戶請(qǐng)求時(shí)候表單驗(yàn)證
from app01 import models from django.forms import ModelForm from django.forms import fieldsclass MyForm(ModelForm):others = fields.CharField()class Meta:model = models = models.UserInfofields = "__all__"@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):form = MyForm20 empty_value_display = "列數(shù)據(jù)為空時(shí),顯示默認(rèn)值"
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin):empty_value_display = "列數(shù)據(jù)為空時(shí),默認(rèn)顯示"list_display = ('user','pwd','up')def up(self,obj):return obj.userup.empty_value_display = "指定列數(shù)據(jù)為空時(shí),默認(rèn)顯示"?
二. Cookie和Session
1.Cookie和Session的基本介紹
cookie不屬于http協(xié)議范圍,由于http協(xié)議無法保持狀態(tài),但實(shí)際情況,我們卻又需要“保持狀態(tài)”,因此cookie就是在這樣一個(gè)場(chǎng)景下誕生。cookie的工作原理是:由服務(wù)器產(chǎn)生cookie內(nèi)容,瀏覽器收到請(qǐng)求響應(yīng)后保存在本地;當(dāng)瀏覽器再次訪問該服務(wù)器時(shí),瀏覽器會(huì)自動(dòng)帶上cookie,這樣服務(wù)器就能通過cookie的內(nèi)容來判斷這個(gè)是“誰(shuí)”。簡(jiǎn)明來說,基于http協(xié)議的無狀態(tài)特征,服務(wù)器根本就不知道訪問者是“誰(shuí)”,那么上述的cookie就起到橋接的作用,我們可以給每個(gè)客戶端的cookie分配一個(gè)唯一的id,這樣用戶在訪問時(shí),通過cookie,服務(wù)器就知道來的人是“誰(shuí)”,然后我們?cè)俑鶕?jù)不同的cookie的id,在服務(wù)器上保存一段時(shí)間的私密資料,如“賬號(hào)密碼”等等。cookie雖然在一定程度上解決了“保持狀態(tài)”的需求,但是由于cookie本身最大支持4096字節(jié),以及cookie本身保存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支持更多的字節(jié),并且他保存在服務(wù)器,有較高的安全性,這便出現(xiàn)了session。
Set-Cookie: NAME=VALUE;Expires/Max-age=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE參數(shù)意義:
- NAME:cookie的名字。
- VALUE:cookie的值。
- Expires:cookie的過期時(shí)間。
- Path:cookie作用的路徑。
- Domain:cookie作用的域名。
- SECURE:是否只在https協(xié)議下起作用。
總結(jié):cookie彌補(bǔ)了http無狀態(tài)的不足,讓服務(wù)器知道來的人是“誰(shuí)”;但是cookie以文本的形式保存在本地,自身安全性較差;所以我們就通過cookie識(shí)別不同的用戶,對(duì)應(yīng)的在session里保存私密的信息以及超過4096字節(jié)的文本。
經(jīng)過前面的學(xué)習(xí)我們已經(jīng)有能力制作一個(gè)登陸頁(yè)面,在驗(yàn)證了用戶名和密碼的正確性后跳轉(zhuǎn)到后臺(tái)的頁(yè)面。但是測(cè)試后也發(fā)現(xiàn),如果繞過登陸頁(yè)面,直接輸入后臺(tái)的url地址也可以直接訪問。這個(gè)顯然是不合理的。其實(shí)我們?nèi)笔У木褪莄ookie和session配合的驗(yàn)證。有了這個(gè)驗(yàn)證過程,我們就可以實(shí)現(xiàn)和其他網(wǎng)站一樣必須登錄才能進(jìn)入后臺(tái)頁(yè)面了。
? ? ? 先說一下這種認(rèn)證的機(jī)制。每當(dāng)我們使用一款瀏覽器訪問一個(gè)登陸頁(yè)面的時(shí)候,一旦我們通過了認(rèn)證。服務(wù)器端就會(huì)發(fā)送一組隨機(jī)唯一的字符串(假設(shè)是123abc)到瀏覽器端,這個(gè)被存儲(chǔ)在瀏覽器端的東西就叫cookie。而服務(wù)器端也會(huì)自己存儲(chǔ)一下用戶當(dāng)前的狀態(tài),比如login=true,username=hahaha之類的用戶信息。但是這種存儲(chǔ)是以字典形式存儲(chǔ)的,字典的唯一key就是剛才發(fā)給用戶的唯一的cookie值。那么如果在服務(wù)器端查看session信息的話,理論上就會(huì)看到如下樣子的字典
{'123abc':{'login':true,'username:hahaha'}}
因?yàn)槊總€(gè)cookie都是唯一的,所以我們?cè)陔娔X上換個(gè)瀏覽器再登陸同一個(gè)網(wǎng)站也需要再次驗(yàn)證。那么為什么說我們只是理論上看到這樣子的字典呢?因?yàn)樘幱诎踩缘目紤],其實(shí)對(duì)于上面那個(gè)大字典不光key值123abc是被加密的,value值{'login':true,'username:hahaha'}在服務(wù)器端也是一樣被加密的。所以我們服務(wù)器上就算打開session信息看到的也是類似與以下樣子的東西{'123abc':dasdasdasd1231231da1231231}
借用一張別的大神畫的圖,可以更直觀的看出來cookie和session的關(guān)系
?
cookie和session的應(yīng)用實(shí)例:
<1>先在templates目錄下創(chuàng)建兩個(gè)html,login.html負(fù)責(zé)登錄頁(yè)面,backend頁(yè)面代表后臺(tái)頁(yè)面
/*---------------------------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 內(nèi)容是 {{ cookie_content }}</h2><h2>session 內(nèi)容是 {{ session_content }}</h2><h2>登錄用戶名 :{{ username }}</h2></div> </body> </html> View Code<2>?在應(yīng)用下的views.py文件,編寫代碼邏輯部分
def login(request):print("COOKIES", request.COOKIES)print("SESSION", request.session)#------------首次進(jìn)入login.html頁(yè)面cookies和session打印內(nèi)容#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單獨(dú)使用---------------------#cookie單獨(dú)使用時(shí),設(shè)置cookiea內(nèi)部字典的內(nèi)容# ret=redirect('/backend/')# ret.set_cookie("username",username)# return ret#----------cookie和sessions結(jié)合使用-----------------# 設(shè)置session內(nèi)部的字典內(nèi)容request.session['is_login'] = 'true'request.session['username'] = 'abc'#登錄成功就將url重定向到后臺(tái)的urlreturn redirect('/backend/')# 登錄不成功或第一訪問就停留在登錄頁(yè)面return render(request,'login.html')def backend(request):print("COOKIES", request.COOKIES)print("SESSION", request.session)#-----------------------cookie單獨(dú)使用------------------# if request.COOKIES.get("username", None):# username = request.COOKIES.get("username", None)# cookie_content = request.COOKIES# return render(request, "backend.html", locals())# #返回值:# # cookie內(nèi)容是{'username': 'abc'}# # session 內(nèi)容是# # 登錄用戶名 :abc#-----------------cookie和session結(jié)合使用-----------------"""這里必須用讀取字典的get()方法把is_login的value缺省設(shè)置為False,當(dāng)用戶訪問backend這個(gè)url先嘗試獲取這個(gè)瀏覽器對(duì)應(yīng)的session中的is_login的值。如果對(duì)方登錄成功的話,在login里就已經(jīng)把is_login的值修改為了True,反之這個(gè)值就是False的"""is_login = request.session.get('is_login', False)# 如果為真,就說明用戶是正常登陸的if is_login:# 獲取字典的內(nèi)容并傳入頁(yè)面文件# 或者用if request.session.get("is_login",None):cookie_content = request.COOKIESsession_content = request.sessionusername = request.session['username']return render(request, 'backend.html',{'cookie_content': cookie_content,'session_content': session_content,'username': username})#返回的值:# cookie 內(nèi)容是 {'csrftoken': 'x8OVNJyVE7SMVgPXTLSoJiNNr6KSTG7CyOwXHoKhBKsFwlCyCXh3UVfHExheoA0g', 'sessionid': '9s3jx5sb5euzdla2d1aq44yrehvun1e2'}# session內(nèi)容是 < django.contrib.sessions.backends.db.SessionStore object at 0x000001BF7D04DDD8 ># 登錄用戶名 :abcelse:"""如果訪問的時(shí)候沒有攜帶正確的session,就直接被重定向url回login頁(yè)面"""return redirect('/login/') View Code<3>編輯urls.py文件,設(shè)置函數(shù)與頁(yè)面的綁定關(guān)系
from django.contrib import admin from django.urls import path from ORM_Study import views from django.conf.urls import urlurlpatterns = [#path('admin/', admin.site.urls),url('^login/',views.login,name='login'),url('^backend/',views.backend,name='backend'), ] View Code<4>最后打開瀏覽器直接訪問/backend/頁(yè)面,檢測(cè)是否直接就被重定向到了/login/頁(yè)面
<5>總結(jié)
從上述步驟中我們看到有一下幾點(diǎn):
(1)login頁(yè)面正確登錄的話,后臺(tái)頁(yè)面可以獲取到瀏覽器攜帶的cookie的。
(2)返回的sessionid其實(shí)就是cookie值
(3)session的內(nèi)容是加密的,從客戶端獲取不到session的內(nèi)容
(4)服務(wù)端可以通過預(yù)設(shè)的key值取出session的內(nèi)容并打印到前段
(5)django的session默認(rèn)是存儲(chǔ)在數(shù)據(jù)庫(kù)里的,我們可以到數(shù)據(jù)庫(kù)查看一下真正session內(nèi)容,在表Django_session里
(6)session的好處:客戶端只有cookie值,始終沒有用戶信息
(7)session依賴于cookie,cookie保存在瀏覽器,session保存在服務(wù)器端。
<6>cookie和session的知識(shí)點(diǎn)總結(jié):
操作cookie:
獲取cookie:request.COOKIES[key]設(shè)置cookie:response.set_cookie(key,value) View Code操作session(session默認(rèn)在服務(wù)器端保存15天):
獲取session:request.session[key]設(shè)置session:reqeust.session[key] = value刪除session:del request.session[key] 設(shè)置session時(shí)效: request.session.set_expiry(value) * 如果value是個(gè)整數(shù),session會(huì)在這些秒數(shù)后失效。 * 如果value是個(gè)datatime或timedelta,session就會(huì)在這個(gè)時(shí)間后失效。 * 如果value是0,用戶關(guān)閉瀏覽器session就會(huì)失效。 * 如果value是None,session會(huì)依賴全局session失效策略。 View Code?>>>>>>>>>待續(xù)
轉(zhuǎn)載于:https://www.cnblogs.com/wuxunyan/p/9141018.html
總結(jié)
以上是生活随笔為你收集整理的Django:Admin,Cookie,Session的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库的日常管理经验浅谈
- 下一篇: 深入使用XMemcached