""" 當咱們須要使用到非django內置的第三方功能或者組件代碼的時候 咱們通常狀況下會建立一個名爲utils文件夾 在該文件夾內對模塊進行功能性劃分 utils能夠在每一個應用下建立 具體結合實際狀況 咱們到了後期封裝代碼的時候 再也不侷限於函數 仍是儘可能朝面向對象去封裝 咱們自定義的分頁器是基於bootstrap樣式來的 因此你須要提早導入bootstrap bootstrap 版本 v3 jQuery 版本 v3 """ # 後端 book_queryset = models.Book.objects.all() current_page = request.GET.get('page',1) all_count = book_queryset.count() # 1 傳值生成對象 page_obj = Pagination(current_page=current_page,all_count=all_count) # 2 直接對總數據進行切片操做 page_queryset = book_queryset[page_obj.start:page_obj.end] # 3 將page_queryset傳遞到頁面 替換以前的book_queryset # 前端 {% for book_obj in page_queryset %} <p>{{ book_obj.title }}</p> <nav aria-label="Page navigation"> </nav> {% endfor %} {#利用自定義分頁器直接顯示分頁器樣式#} {{ page_obj.page_html|safe }} """ 大家只須要掌握如何拷貝使用 以及大體的推導思路便可 """
""" 寫一個註冊功能 獲取用戶名和密碼 利用form表單提交數據 在後端判斷用戶名和密碼是否符合必定的條件 用戶名中不能含有金梅 密碼不能少於三位 如何符合條件須要你將提示信息展現到前端頁面 """ def ab_form(request): back_dic = {'username':'','password':''} if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if '金梅' in username: back_dic['username'] = '不符合社會主義核心價值觀' if len(password) < 3: back_dic['password'] = '不能過短 很差!' """ 不管是post請求仍是get請求 頁面都可以獲取到字典 只不過get請求來的時候 字典值都是空的 而post請求來以後 字典可能有值 """ return render(request,'ab_form.html',locals()) <form action="" method="post"> <p>username: <input type="text" name="username"> <span style="color: red">{{ back_dic.username }}</span> </p> <p>password: <input type="text" name="password"> <span style="color: red">{{ back_dic.password }}</span> </p> <input type="submit" class="btn btn-info"> </form> """ 1.手動書寫前端獲取用戶數據的html代碼 渲染html代碼 2.後端對用戶數據進行校驗 校驗數據 3.對不符合要求的數據進行前端提示 展現提示信息 forms組件 可以完成的事情 1.渲染html代碼 2.校驗數據 3.展現提示信息 爲何數據校驗非要去後端 不能在前端利用js直接完成呢? 數據校驗前端無關緊要 可是後端必需要有!!! 由於前端的校驗是弱不由風的 你能夠直接修改 或者利用爬蟲程序繞過前端頁面直接朝後端提交數據 購物網站 選取了貨物以後 會計算一個價格發送給後端 若是後端不作價格的校驗 實際是獲取到用戶選擇的全部商品的主鍵值 而後在後端查詢出全部商品的價格 再次計算一遍 若是跟前端一致 那麼完成支付若是不一致直接拒絕 """
from django import forms
class MyForm(forms.Form):
# username字符串類型最小3位最大8位
username = forms.CharField(min_length=3,max_length=8)
# password字符串類型最小3位最大8位
password = forms.CharField(min_length=3,max_length=8)
# email字段必須符合郵箱格式 xxx@xx.com
email = forms.EmailField()
"""
1.測試環境的準備 能夠本身拷貝代碼準備
2.其實在pycharm裏面已經幫你準備一個測試環境
python console
"""
from app01 import views
# 1 將帶校驗的數據組織成字典的形式傳入便可
form_obj = views.MyForm({'username':'jason','password':'123','email':'123'})
# 2 判斷數據是否合法 注意該方法只有在全部的數據所有合法的狀況下才會返回True
form_obj.is_valid()
False
# 3 查看全部校驗經過的數據
form_obj.cleaned_data
{'username': 'jason', 'password': '123'}
# 4 查看全部不符合校驗規則以及不符合的緣由
form_obj.errors
{
'email': ['Enter a valid email address.']
}
# 5 校驗數據只校驗類中出現的字段 多傳不影響 多傳的字段直接忽略
form_obj = views.MyForm({'username':'jason','password':'123','email':'123@qq.com','hobby':'study'})
form_obj.is_valid()
True
# 6 校驗數據 默認狀況下 類裏面全部的字段都必須傳值
form_obj = views.MyForm({'username':'jason','password':'123'})
form_obj.is_valid()
False
"""
也就意味着校驗數據的時候 默認狀況下數據能夠多傳可是毫不可能少傳
"""
""" forms組件只會自動幫你渲染獲取用戶輸入的標籤(input select radio checkbox) 不能幫你渲染提交按鈕 """ def index(request): # 1 先產生一個空對象 form_obj = MyForm() # 2 直接將該空對象傳遞給html頁面 return render(request,'index.html',locals()) # 前端利用空對象作操做 <p>第一種渲染方式:代碼書寫極少,封裝程度過高 不便於後續的擴展 通常狀況下只在本地測試使用</p> {{ form_obj.as_p }} {{ form_obj.as_ul }} {{ form_obj.as_table }} <p>第二種渲染方式:可擴展性很強 可是須要書寫的代碼太多 通常狀況下不用</p> <p>{{ form_obj.username.label }}:{{ form_obj.username }}</p> <p>{{ form_obj.password.label }}:{{ form_obj.password }}</p> <p>{{ form_obj.email.label }}:{{ form_obj.email }}</p> <p>第三種渲染方式(推薦使用):代碼書寫簡單 而且擴展性也高</p> {% for form in form_obj %} <p>{{ form.label }}:{{ form }}</p> {% endfor %} """ label屬性默認展現的是類中定義的字段首字母大寫的形式 也能夠本身修改 直接給字段對象加label屬性便可 username = forms.CharField(min_length=3,max_length=8,label='用戶名') """
""" 瀏覽器會自動幫你校驗數據 可是前端的校驗弱不由風 如何讓瀏覽器不作校驗 <form action="" method="post" novalidate> """ def index(request): # 1 先產生一個空對象 form_obj = MyForm() if request.method == 'POST': # 獲取用戶數據而且校驗 """ 1.數據獲取繁瑣 2.校驗數據須要構形成字典的格式傳入才行 ps:可是request.POST能夠當作就是一個字典 """ # 3.校驗數據 form_obj = MyForm(request.POST) # 4.判斷數據是否合法 if form_obj.is_valid(): # 5.若是合法 操做數據庫存儲數據 return HttpResponse('OK') # 5.不合法 有錯誤 # 2 直接將該空對象傳遞給html頁面 return render(request,'index.html',locals()) {% for form in form_obj %} <p> {{ form.label }}:{{ form }} <span style="color: red">{{ form.errors.0 }}</span> </p> {% endfor %} """ 1.必備的條件 get請求和post傳給html頁面對象變量名必須同樣 2.forms組件當你的數據不合法的狀況下 會保存你上次的數據 讓你基於以前的結果進行修改 更加的人性化 """ # 針對錯誤的提示信息還能夠本身自定製 class MyForm(forms.Form): # username字符串類型最小3位最大8位 username = forms.CharField(min_length=3,max_length=8,label='用戶名', error_messages={ 'min_length':'用戶名最少3位', 'max_length':'用戶名最大8位', 'required':"用戶名不能爲空" } ) # password字符串類型最小3位最大8位 password = forms.CharField(min_length=3,max_length=8,label='密碼', error_messages={ 'min_length': '密碼最少3位', 'max_length': '密碼最大8位', 'required': "密碼不能爲空" } ) # email字段必須符合郵箱格式 xxx@xx.com email = forms.EmailField(label='郵箱', error_messages={ 'invalid':'郵箱格式不正確', 'required': "郵箱不能爲空" } )
"""
在特定的節點自動觸發完成響應操做
鉤子函數在forms組件中就相似於第二道關卡,可以讓咱們自定義校驗規則
在forms組件中有兩類鉤子
1.局部鉤子
當你須要給單個字段增長校驗規則的時候可使用
2.全局鉤子
當你須要給多個字段增長校驗規則的時候可使用
"""
# 實際案例
# 1.校驗用戶名中不能含有666 只是校驗username字段 局部鉤子
# 2.校驗密碼和確認密碼是否一致 password confirm兩個字段 全局鉤子
# 鉤子函數 在類裏面書寫方法便可
# 局部鉤子
def clean_username(self):
# 獲取到用戶名
username = self.cleaned_data.get('username')
if '666' in username:
# 提示前端展現錯誤信息
self.add_error('username','光喊666是不行滴~')
# 將鉤子函數鉤去出來數據再放回去
return username
# 全局鉤子
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not confirm_password == password:
self.add_error('confirm_password','兩次密碼不一致')
# 將鉤子函數鉤出來數據再放回去
return self.cleaned_data
label 字段名
error_messages 自定義報錯信息
initial 默認值
required 控制字段是否必填
"""
1.字段沒有樣式
2.針對不一樣類型的input如何修改
text
password
date
radio
checkbox
...
"""
widget=forms.widgets.PasswordInput(attrs={'class':'form-control c1 c2'})
# 多個屬性值的話 直接空格隔開便可
# 第一道關卡里面還支持正則校驗
validators=[
RegexValidator(r'^[0-9]+$', '請輸入數字'),
RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')
]
其餘類型渲染html
# radio
gender = forms.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性別",
initial=3,
widget=forms.widgets.RadioSelect()
)
# select
hobby = forms.ChoiceField(
choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
label="愛好",
initial=3,
widget=forms.widgets.Select()
)
# 多選
hobby1 = forms.MultipleChoiceField(
choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
label="愛好",
initial=[1, 3],
widget=forms.widgets.SelectMultiple()
)
# 單選checkbox
keep = forms.ChoiceField(
label="是否記住密碼",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
# 多選checkbox
hobby2 = forms.MultipleChoiceField(
choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
label="愛好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)