Form
django中的Form一般有兩種功能:
1、輸入html
2、驗證用戶輸入
最簡易的form驗證:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .inline-group{ position: relative; padding: 5px; width: 250px; } .input-group input{ width: 200px; display: inline-block; } .inline-group span{ display: inline-block; position: absolute; height: 12px; font-size: 8px; border: 1px solid darkorchid; background-color: chartreuse; color: aliceblue; top: 41px; left: 20px; width: 202px; } </style> </head> <body> <form action="form1/" method="POST"> <div class="inline-group"> {{ form.user }} {#創建user的input標簽#} {% if error.user.0 %} {#如果出錯誤就把錯誤信息顯示出來,否則隱藏#} <span>{{ error.user.0 }}</span> {# 獲得錯誤信息#} {% endif %} </div> <div class="inline-group"> {{ form.pwd }} {# 創建pwd的input標簽#} {% if error.pwd.0 %} <span>{{ error.pwd.0 }}</span> {% endif %} </div> <div > <input type="submit" value="提交"/> </div> </form> </body> </html>
# !/usr/bin/env python # -*- coding:utf-8 -*- from django.shortcuts import render from app01.forms import Form1 from django.forms.utils import ErrorDict def form1(request): if request.method == 'POST': # 判斷是否是通過POST方法獲取 # request.POST.get('user', None) # request.POST.get('pwd', None) # 獲取請求內容,做驗證 f = Form1(request.POST) if f.is_valid(): print(f.cleaned_data) else: print(type(f.errors), f.errors) return render(request, 'account/form1.html', {'error': f.errors}) # {'error': f.errors}錯誤信息 else: f = Form1() return render(request, 'account/form1.html', {'form': f})
上面的只是實現最簡易的form驗證,更沒法在生產環境下運用;要想在生產環境下運用就需要我們根據業務需求自定制form驗證。
下面我們來寫一個比較差不多的自定制的form驗證。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .input-group{ position: relative; padding: 5px; width: 250px; } .input-group input{ width: 200px; display: inline-block; } .input-group span{ display: inline-block; position: absolute; height: 12px; font-size: 8px; border: 1px solid darkred; background-color: coral; color: white; top: 41px; left: 20px; width: 202px; } </style> </head> <body> <form action="/form1/" method="POST"> <div class="input-group"> {{ form.user }} {% if error.user.0 %} <span>{{ error.user.0 }}</span> {% endif %} </div> <div class="input-group"> {{ form.pwd }} {% if error.pwd.0 %} <span>{{ error.pwd.0 }}</span> {% endif %} </div> <div class="input-group"> {{ form.email }} {% if error.email.0 %} <span>{{ error.email.0 }}</span> {% endif %} </div> <div class="input-group"> {{ form.memo }} {% if error.memo.0 %} <span>{{ error.memo.0 }}</span> {% endif %} </div> <div class="input-group"> {{ form.book_type }} {% if error.book_type.0 %} <span>{{ error.book_type.0 }}</span> {% endif %} </div> <div> <input type="submit" value="提交"/> </div> </form> </body> </html>
#!/usr/bin/env python # -*- coding:utf-8 -*- from django import forms from app01 import models class Form1(forms.Form): user = forms.CharField( widget=forms.TextInput(attrs={'class': 'c1'}), # attrs參數給標簽加樣式(添加樣式) error_messages={'required': '用戶名不能為空'},) # error_messages為自定義錯誤信息(定制錯誤信息) pwd = forms.CharField(max_length=4,min_length=2) # 參數是最多4個,最少兩個(定義字符長短) email = forms.EmailField(error_messages={'required': '郵箱不能為空', 'invalid': '郵箱格式錯誤'}) # # required表示不能為空的錯誤提示,invalid格式錯誤提示 memo = forms.CharField( widget=forms.Textarea() # 生成Textarea標簽 ) # user_type_choice = ( # (0, '普通用戶'), # (1, '高級用戶'), # ) user_type_choice = models.BookType.objects.values_list('id','caption') # 也可以通過映射values_list,弄一個字典在數據庫取相應的下拉選項內容 book_type = forms.CharField( # 下拉框選項(下拉選項可以在上面定義好) widget=forms.widgets.Select(choices=user_type_choice,attrs={'class': "form-control"})) def __init__(self,*args, **kwargs): # 創建Init方法在每次創建對象的時候再執行一次,檢查下數據庫是否修改過 super(Form1, self).__init__(*args, **kwargs) self.fields['book_type'] = forms.CharField( # 在數據庫查看是否修改過,並拿值。 widget=forms.widgets.Select(choices=models.BookType.objects.values_list('id','caption'),attrs={'class': "form-control"}))
擴展:ModelForm
在使用Model和Form時,都需要對字段進行定義並指定類型,通過ModelForm則可以省去From中字段的定義
class AdminModelForm(forms.ModelForm): class Meta: model = models.Admin #fields = '__all__' fields = ('username', 'email') widgets = { 'email' : forms.PasswordInput(attrs={'class':"alex"}), }
上面都是簡單的整體的整理下form驗證,這不是Form的全部,下面我在重新過一遍相對比較全些的Form。
1、輸入html
from django.shortcuts import render
from django import forms
class UserForm(forms.Form):
host = forms.CharField()
port = forms.CharField()
email = forms.EmailField()
mobile = forms.CharField()
def user_list(request):
obj = UserForm()
return render(request,"index.html",{"obj":obj})
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/app01/user_list/">
<!--自動生成input標簽-->
<p>主機:{{ obj.host }}</p>
<p>端口:{{ obj.port }}</p>
<p>郵箱:{{ obj.email }}</p>
<p>手機:{{ obj.mobile }}</p>
<input type="submit">
</form>
</body>
</html>
2、驗證
from django.shortcuts import render
from django import forms
class UserForm(forms.Form):
host = forms.CharField()
port = forms.CharField()
email = forms.EmailField()
mobile = forms.CharField()
def user_list(request):
obj = UserForm()
if request.method == "POST": # 判斷是否post方式
user_input_obj = UserForm(request.POST) # 把提交過來的數據封裝到UserForm,UserForm會自動把數據封裝到user_input_obj
if user_input_obj.is_valid(): # 驗證用戶輸入是否合法
data = user_input_obj.clean() # 合法,獲取數據
else:
error_msg = user_input_obj.errors # 不合法,返回錯誤信息
return render(request,"index.html",{"obj":user_input_obj,"error":error_msg})
return render(request,"index.html",{"obj":obj})
優化
def user_list(request):
obj = UserForm(request.POST) # 如果有數據,把提交過來的數據封裝到UserForm,UserForm會自動把數據封裝到user_input_obj
if request.method == "POST":
if obj.is_valid(): # 驗證用戶輸入是否合法
data = obj.clean() # 合法,獲取數據
else:
error_msg = obj.errors.as_data() # 不合法,返回錯誤信息
return render(request,"index.html",{"obj":obj,"error":error_msg})
return render(request,"index.html",{"obj":obj,})
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/app01/user_list/" method="post">
<!--自動生成input標簽-->
<p>主機:{{ obj.host }}<span>{{ error.host }}</span></p>
<p>端口:{{ obj.port }}<span>{{ error.port }}</span></p>
<p>郵箱:{{ obj.email }}<span>{{ error.email }}</span></p>
<p>手機:{{ obj.mobile }}<span>{{ error.mobile }}</span></p>
<input type="submit">
</form>
</body>
</html>
3、定制From表單
(1)設置報錯信息,添加屬性樣式
class UserForm(forms.Form):
host = forms.CharField(error_messages={"required":"主機不能為空"},#設置顯示的錯誤信息
widget=forms.TextInput(attrs={"class":"form-control",
"placeholder": "主機"})#添加屬性和樣式
)
port = forms.CharField()
email = forms.EmailField()
mobile = forms.CharField()
(2)多行文本框
#多行文本框,備注
memo = forms.CharField(required=False, #可以為空
widget=forms.Textarea(attrs={"class":"form-control",
"placeholder": "備注"})#添加屬性和樣式
)
(3)下拉框
#下拉框
user_type_choice=(
(0,"普通用戶"),
(1,"高級用戶")
)
user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
attrs={'class': "form-control"}))
(4)動態生成select標簽
文件中取數據
#動態下拉框
u_type = forms.IntegerField(widget=forms.widgets.Select( attrs={'class': "form-control"}))
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
import json
f=open("u_type_db")
data = f.read()
data_tuple = json.loads(data)
self.fields['u_type'].widget.choices = data_tuple
user_type_choice = (
(0, "普通用戶"),
(1, "高級用戶")
)
數據庫中取數據
最開始的form就是數據庫中去數據,而且在數據庫修改時,下拉框的內容不需要刷新頁面也可以生成。
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
data_tuple=models.UserInfo.objects.all().values_list('id','username')
self.fields['u_type'].widget.choices = data_tuple
(5)自定義驗證條件
#自定義驗證
def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手機號碼格式錯誤')
class UserForm(forms.Form):
mobile = forms.CharField(validators=[mobile_validate, ])#添加自定義手機號驗證
4、美化顯示錯誤信息
def user_list(request):
obj = UserForm()
if request.method == "POST":
user_input_obj = UserForm(request.POST)#把提交過來的數據封裝到UserForm,UserForm會自動把數據封裝到user_input_obj
if user_input_obj.is_valid(): #驗證用戶輸入是否合法
data = user_input_obj.clean() #合法,獲取數據
else:
error_msg = user_input_obj.errors #不合法,返回錯誤信息
return render(request,"index.html",{"obj":user_input_obj,"error":error_msg})
return render(request,"index.html",{"obj":obj,})
默認顯示ul樣式,不美觀
error_msg = user_input_obj.errors #不合法,返回錯誤信息

改成as_data()后只顯示一個字符串格式
error_msg = user_input_obj.errors.as_data() #不合法,返回錯誤信息

修改方法:
1、定義

2、在html頂部調用
{% load form_tag %}
3、引用
<p>主機:{{ obj.host }}<span>{% error_message error.host %}</span></p>
as_json()用於ajax返回
error_msg = user_input_obj.errors.as_json()#不合法,返回錯誤信息 return HttpResponse(error_msg )
實例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/app01/user_list/"> <!--自動生成input標簽--> {# <p>主機:{{ obj.host }}</p>#} {# <p>端口:{{ obj.port }}</p>#} {# <p>郵箱:{{ obj.email }}</p>#} {# <p>手機:{{ obj.mobile }}</p>#} {# <input type="submit">#} {# 進一步優化#} <p>主機:{{ obj.host }}<span>{{ error.host }}</span></p> <p>端口:{{ obj.port }}<span>{{ error.port }}</span></p> <p>郵箱:{{ obj.email }}<span>{{ error.email }}</span></p> <p>手機:{{ obj.mobile }}<span>{{ error.mobile }}</span></p> <p>備注:{{ obj.memo }}<span>{{ error.memo }}</span></p> <p>用戶類型:{{ obj.user_type }}<span>{{ error.user_type }}</span></p> <input type="submit"> </form> </body> </html>
from django.shortcuts import render
from django import forms
import re
from django.core.exceptions import ValidationError
# 自定義驗證
def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手機號碼格式錯誤')
class UserForm(forms.Form):
host = forms.CharField(error_messages={"required": "主機不能為空"}, # 設置顯示的錯誤信息
widget=forms.TextInput(attrs={"class": "form-control",
"placeholder": "主機"}) # 添加屬性和樣式
)
port = forms.CharField(error_messages={"required": "端口不能為空"},
widget=forms.TextInput(attrs={"class": "form-control",
"placeholder": "端口"})
)
email = forms.EmailField(error_messages={"required": "郵箱不能為空"},
widget=forms.TextInput(attrs={"class": "form-control",
"placeholder": "郵箱"})
)
mobile = forms.CharField(error_messages={"required": "手機不能為空"},
widget=forms.TextInput(attrs={"class": "form-control",
"placeholder": "手機"}),
validators=[mobile_validate]) # 添加自定義驗證
# 多行文本框,備注
memo = forms.CharField(required=False, # 可以為空
widget=forms.Textarea(attrs={"class": "form-control",
"placeholder": "備注"}) # 添加屬性和樣式
)
# 下拉框
user_type_choice = (
(0, "普通用戶"),
(1, "高級用戶")
)
user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
attrs={'class': "form-control"}))
def user_list(request):
obj = UserForm()
if request.method == "POST":
user_input_obj = UserForm(request.POST) # 把提交過來的數據封裝到UserForm,UserForm會自動把數據封裝到user_input_obj
if user_input_obj.is_valid(): # 驗證用戶輸入是否合法
data = user_input_obj.clean() # 合法,獲取數據
print(data)
else:
error_msg = user_input_obj.errors.as_data() # 不合法,返回錯誤信息
return render(request, "index.html", {"obj": user_input_obj, "error": error_msg})
return render(request, "index.html", {"obj": obj})
5、分頁
一、Django內置分頁
Paginator
二、自定義分頁
分頁功能在每個網站都是必要的,對於分頁來說,其實就是根據用戶的輸入計算出應該在數據庫表中的起始位置。
1、設定每頁顯示數據條數
2、用戶輸入頁碼(第一頁、第二頁...)
3、根據設定的每頁顯示條數和當前頁碼,計算出需要取數據表的起始位置
4、在數據表中根據起始位置取值,頁面上輸出數據
需求又來了,需要在頁面上顯示分頁的頁面。如:[上一頁][1][2][3][4][5][下一頁]
1、設定每頁顯示數據條數
2、用戶輸入頁碼(第一頁、第二頁...)
3、設定顯示多少頁號
4、獲取當前數據總條數
5、根據設定顯示多少頁號和數據總條數計算出,總頁數
6、根據設定的每頁顯示條數和當前頁碼,計算出需要取數據表的起始位置
7、在數據表中根據起始位置取值,頁面上輸出數據
8、輸出分頁html,如:[上一頁][1][2][3][4][5][下一頁]
#!/usr/bin/env python # _*_coding:utf-8_*_ from django.utils.safestring import mark_safe class PageInfo(object): def __init__(self,current,totalItem,peritems=5): self.__current=current self.__peritems=peritems self.__totalItem=totalItem def From(self): return (self.__current-1)*self.__peritems def To(self): return self.__current*self.__peritems def TotalPage(self): #總頁數 result=divmod(self.__totalItem,self.__peritems) if result[1]==0: return result[0] else: return result[0]+1 def Custompager(baseurl,currentPage,totalpage): #基礎頁,當前頁,總頁數 perPager=11 #總頁數<11 #0 -- totalpage #總頁數>11 #當前頁大於5 currentPage-5 -- currentPage+5 #currentPage+5是否超過總頁數,超過總頁數,end就是總頁數 #當前頁小於5 0 -- 11 begin=0 end=0 if totalpage <= 11: begin=0 end=totalpage else: if currentPage>5: begin=currentPage-5 end=currentPage+5 if end > totalpage: end=totalpage else: begin=0 end=11 pager_list=[] if currentPage<=1: first="<a href=''>首頁</a>" else: first="<a href='%s%d'>首頁</a>" % (baseurl,1) pager_list.append(first) if currentPage<=1: prev="<a href=''>上一頁</a>" else: prev="<a href='%s%d'>上一頁</a>" % (baseurl,currentPage-1) pager_list.append(prev) for i in range(begin+1,end+1): if i == currentPage: temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i) else: temp="<a href='%s%d'>%d</a>" % (baseurl,i,i) pager_list.append(temp) if currentPage>=totalpage: next="<a href='#'>下一頁</a>" else: next="<a href='%s%d'>下一頁</a>" % (baseurl,currentPage+1) pager_list.append(next) if currentPage>=totalpage: last="<a href=''>末頁</a>" else: last="<a href='%s%d'>末頁</a>" % (baseurl,totalpage) pager_list.append(last) result=''.join(pager_list) return mark_safe(result) #把字符串轉成html語言
總結,分頁時需要做三件事:
- 創建處理分頁數據的類
- 根據分頁數據獲取數據
- 輸出分頁HTML,即:[上一頁][1][2][3][4][5][下一頁]
Cookie
在瀏覽器端(客戶端)保存的鍵值對,特性:每次http請求都會攜帶
1、獲取Cookie
request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
參數:
default: 默認值
salt: 加密鹽
max_age: 后台控制過期時間
2、設置Cookie
def cook2(request):
print(request.COOKIES)
# print(request.get_signed_cookie('k2',None,salt='uuu'))
# rep = HttpResponse('ok')
# rep.set_cookie('k1',123)
# rep.set_signed_cookie('k2',666,salt='uuu')
rep = HttpResponse('ok')
return rep
3、Cookie的參數
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密鹽',...)
參數:
key, 鍵
value='', 值
max_age=None, 超時時間 單位是秒數
expires=None, 超時時間(IE requires expires, so set it if hasn't been already.) 支持datetime、時間戳time.time這兩種
path='/', Cookie生效的路徑,/ 表示根路徑,特殊的:跟路徑的cookie可以被任何url的頁面訪問
domain=None, Cookie生效的域名
secure=False, https傳輸
httponly=False 只能http協議傳輸,無法被JavaScript獲取(不是絕對,底層抓包可以獲取到也可以被覆蓋)
示例:
def cook1(request): # print(request.COOKIES) # 獲取我所有Cookie # print(request.get_signed_cookie('k2',None,salt='uuu')) # 獲取加鹽的cookie # rep = HttpResponse('ok') # rep.set_cookie('k1',123) # 設置cookie # rep.set_signed_cookie('k2',666,salt='uuu') # 簽名的cookie;salt為加鹽 rep = HttpResponse('cook1') rep.set_cookie('k999', 123, path='/cook1/') # path是cookie生效的路徑(局部的);/ 表示根路徑,特殊的:跟路徑的cookie可以被任何url的頁面訪問 rep.set_cookie('k888', 123) # 全局的cookie return rep
由於cookie保存在客戶端的電腦上,所以,JavaScript和jquery也可以操作cookie。
<script src='/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });
Session
解析
生成隨機字符串,並在服務端保存特定信息;
Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:
使用以下的類型只需要在引擎修改下配置換成相應的類型就可以了。
1、數據庫(默認)
2、緩存
3、文件
4、緩存+數據庫
5、加密cookie
1、數據庫Session
Django默認支持Session,並且默認是將Session數據存儲在數據庫中,即:django_session 表中。
配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默認) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑(默認) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默認) SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie(默認) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸(默認) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過期(默認) SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改之后才保存(默認)
使用 def index(request): # 獲取、設置、刪除Session中數據 request.session['k1'] # 獲取 request.session.get('k1',None) request.session['k1'] = 123 # 設置 request.session.setdefault('k1',123) # 設置,存在則不設置 del request.session['k1'] # 獲取所有 鍵、值、鍵值對 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems() # 用戶session的隨機字符串(存在客戶端瀏覽器中,也存在服務端的數據庫中) request.session.session_key # 將所有Session失效日期小於當前日期的數據刪除 request.session.clear_expired() # 檢查 用戶session的隨機字符串 在數據庫中是否 request.session.exists("session_key") # 刪除當前用戶的所有Session數據 request.session.delete("session_key")
示例:
def session(request):
# request.session
request.session['k1'] = 123 # 設置session
# request.session['k1']
print(request.session.session_key) # 獲得用戶session的隨機字符串(存在客戶端瀏覽器中,也存在服務端的數據庫中)
return HttpResponse('session')
def index(request): # 獲得session
return HttpResponse(request.session['k1']) # 這里可以直接讀取到session
2、緩存Session
配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的緩存別名(默認內存緩存,也可以是memcache),此處別名依賴緩存的設置 SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名 SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過期 SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改之后才保存
使用和數據庫Session使用一樣,只需要修改下配置就可以。
3、文件Session
配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 緩存文件路徑,如果為None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir() #如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名 SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過期 SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改之后才保存
使用同上,在settings中修改下配置
4、緩存+數據庫Session
數據庫用於做持久化,緩存用於提高效率 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
使用同上,在settings中修改下配置
5、加密cookie Session
配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
使用同上,在settings中修改下配置
登錄認證實例:
<form class="common_form" id="Form" method="post" action="/app01/login/"> <div><h1 class="login_title">登錄</h1></div> <div style="width: 600px"> <div class="form_group"><input name="username" class="form-control" label='用戶名' type="text" placeholder="用戶名" require='true'></div> </div> <div style="width: 600px"> <div class="form_group"><input name="password" class="form-control" label='密碼' type="password" placeholder="密碼" require='true'></div> </div> <div class="form_group"><input class="btn btn-info form_btn" type="submit" value="登錄"></div> </form>
def login(request): if request.method == "POST": username = request.POST.get("username") password = request.POST.get("password") if username == "zhangsan" and password == "123456": request.session["IS_LOGIN"] = True #創建session return redirect("/app01/home/") return render(request,"app01/login.html") def home(request): islogin = request.session.get("IS_LOGIN",False) if islogin:#如果用戶已登錄 return render(request,"app01/menus.html") else: return redirect("/app01/login/") def logout(request):#退出 try: del request.session['IS_LOGIN'] except KeyError: pass return redirect("/app01/login/")
CSRF(跨站請求偽造)
1、簡介
django為用戶實現防止跨站請求偽造的功能,通過中間件django.middleware.csrf.CsrfViewMiddleware 來完成。
對於django中設置防跨站請求偽造功能分為全局和局部。
全局:
中間件 django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_protect,為當前函數強制設置防跨站請求偽造功能,即便settings中沒有設置全局中間件。
@csrf_protect,取消當前函數防跨站請求偽造功能,即便settings中設置了全局中間件。
默認(全局):'django.middleware.csrf.CsrfViewMiddleware' 中間間,過濾所有post的請求。是為全局的,需要遵循下面 在html中加上{% csrf_token %} views:的返回用render方法 去掉(全局):'django.middleware.csrf.CsrfViewMiddleware'就不需要遵循csrf 設置(局部)也可以通過裝飾器來設定局部的CSRF。(指定某些遵循csrf) @csrf_protect 在html中加上{% csrf_token %} views:的返回用render 使用裝飾器也可以(局部)不遵循CSRF(指定某些不遵循csrf) @csrf_exempt
2、應用
2.1、普通表單
veiw中設置返回值:
return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
# render_to_response需要context_instance=RequestContext(request)這個參數,因為render_to_response不生成隨機字符串。
或者 return render(request, 'xxx.html', data) html中設置Token: {% csrf_token %}
2.2、Ajax
對於傳統的form,可以通過表單的方式將token再次發送到服務端,而對於ajax的話,使用如下方式。
from django.template.context import RequestContext # Create your views here. def test(request): if request.method == 'POST': print request.POST return HttpResponse('ok') return render_to_response('app01/test.html',context_instance=RequestContext(request))
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> {% csrf_token %} <input type="button" onclick="Do();" value="Do it"/> <script src="/static/plugin/jquery/jquery-1.8.0.js"></script> <script src="/static/plugin/jquery/jquery.cookie.js"></script> <script type="text/javascript"> var csrftoken = $.cookie('csrftoken'); // 獲取 function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ // 是一個全局的配置,在所有的ajax發來之前執行 beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); // 在發ajax之前設置一個請求頭,名字是X-CSRFToken, // 在ajax發送之前把請求頭放到csrftoken,在一塊發過去,對的就執行 } } }); // 上面是獲取token,在以后ajax操作前,寫上面這個配置。 function Do(){ $.ajax({ url:"/app01/test/", data:{id:1}, type:'POST', success:function(data){ console.log(data); } }); } </script> </body> </html>
更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
admin
django amdin是django提供的一個后台管理頁面,改管理頁面提供完善的html和css,使得你在通過Model創建完數據庫表之后,
就可以對數據進行增刪改查,而使用django admin 則需要以下步驟:
1、創建后台管理員
2、配置url
3、注冊和配置django admin后台管理頁面
1、創建后台管理員
python manage.py createsuperuser
2、配置后台管理url
url(r'^admin/', include(admin.site.urls)),
3、注冊和配置django admin 后台管理頁面
a、在admin中執行如下配置
from django.contrib import admin from app01 import models admin.site.register(models.UserType) admin.site.register(models.UserInfo) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
b、設置數據表名稱
class UserType(models.Model):
name = models.CharField(max_length=50)
class Meta:
verbose_name = '用戶類型'
verbose_name_plural = '用戶類型'
c、打開表之后,設定默認顯示,需要在model中作如下配置
class UserType(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
from django.contrib import admin
from app01 import models
class UserInfoAdmin(admin.ModelAdmin):
list_display = ('username', 'password', 'email')
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
d、為數據表添加搜索功能
from django.contrib import admin
from app01 import models
class UserInfoAdmin(admin.ModelAdmin):
list_display = ('username', 'password', 'email')
search_fields = ('username', 'email')
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
e、添加快速過濾
from django.contrib import admin
from app01 import models
class UserInfoAdmin(admin.ModelAdmin):
list_display = ('username', 'password', 'email')
search_fields = ('username', 'email')
list_filter = ('username', 'email')
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
更多詳見:http://www.cnblogs.com/wupeiqi/articles/5237704.html
http://www.cnblogs.com/wupeiqi/articles/5246483.html
