68-django-自定義分頁器、form組件

今日內容概要

  • 自定義分頁器的拷貝及使用html

  • 校驗性組件:form組件前端

    組件有不少不少,就相似於功能模塊python

今日內容詳細

自定義分頁器的拷貝及使用

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封裝分頁相關數據
        :param current_page: 當前頁
        :param all_count:    數據庫中的數據總條數
        :param per_page_num: 每頁顯示的數據條數
        :param pager_count:  最多顯示的頁碼個數
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # 總頁碼
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 若是總頁碼 < 11個:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 總頁碼  > 11
        else:
            # 當前頁若是<=頁面上最多顯示11/2個頁碼
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 當前頁大於5
            else:
                # 頁碼翻到最後
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul標籤
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首頁</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一頁</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一頁</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一頁</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一頁</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾頁</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加標籤
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)
自定義分頁器拷貝體
 1 """
 2 當咱們須要使用到非django內置的第三方功能或者組件代碼的時候
 3 咱們通常狀況下會建立一個名爲utils文件夾 在該文件夾內對模塊進行功能性劃分
 4     utils能夠在每一個應用下建立 具體結合實際狀況
 5 
 6 咱們到了後期封裝代碼的時候 再也不侷限於函數
 7 仍是儘可能朝面向對象去封裝
 8 
 9 咱們自定義的分頁器是基於bootstrap樣式來的 因此你須要提早導入bootstrap
10     bootstrap 版本 v3
11     jQuery        版本 v3
12 """
13 # 後端
14 book_queryset = models.Book.objects.all()
15 current_page = request.GET.get('page',1)
16 all_count = book_queryset.count()
17 # 1 傳值生成對象
18 page_obj = Pagination(current_page=current_page,all_count=all_count)
19 # 2 直接對總數據進行切片操做
20 page_queryset = book_queryset[page_obj.start:page_obj.end]
21 # 3 將page_queryset傳遞到頁面 替換以前的book_queryset
22 
23 
24 # 前端
25 {% for book_obj in page_queryset %}
26     <p>{{ book_obj.title }}</p>
27 {% endfor %}
28 {#利用自定義分頁器直接顯示分頁器樣式#}
29 {{ page_obj.page_html|safe }}
30   
31 """
32 大家只須要掌握如何拷貝使用 以及大體的推導思路便可
33 """

Forms組件

前戲

 1 """
 2 寫一個註冊功能
 3     獲取用戶名和密碼 利用form表單提交數據
 4     在後端判斷用戶名和密碼是否符合必定的條件
 5         用戶名中不能含有嚶嚶嚶
 6         密碼不能少於三位
 7     
 8     如何符合條件須要你將提示信息展現到前端頁面
 9 """
10 def ab_form(request):
11     back_dic = {'username':'','password':''}
12     if request.method == 'POST':
13         username = request.POST.get('username')
14         password = request.POST.get('password')
15         if '嚶嚶嚶' in username:
16             back_dic['username'] = '你嚶nm'
17         if len(password) < 3:
18             back_dic['password'] = '不能過短 很差!'
19     """
20     不管是post請求仍是get請求
21     頁面都可以獲取到字典 只不過get請求來的時候 字典值都是空的
22     而post請求來以後 字典可能有值
23     """
24     return render(request,'ab_form.html',locals())
25 
26 <form action="" method="post">
27     <p>username:
28         <input type="text" name="username">
29         <span style="color: red">{{ back_dic.username }}</span>
30     </p>
31     <p>password:
32         <input type="text" name="password">
33         <span style="color: red">{{ back_dic.password }}</span>
34     </p>
35     <input type="submit" class="btn btn-info">
36 </form>
37 
38 
39 """
40 1.手動書寫前端獲取用戶數據的html代碼                        渲染html代碼
41 2.後端對用戶數據進行校驗                                             校驗數據
42 3.對不符合要求的數據進行前端提示                                展現提示信息
43 
44 forms組件
45     可以完成的事情
46             1.渲染html代碼
47             2.校驗數據
48             3.展現提示信息
49 
50 爲何數據校驗非要去後端 不能在前端利用js直接完成呢?
51     數據校驗前端無關緊要
52     可是後端必需要有!!!
53     
54     由於前端的校驗是弱不由風的 你能夠直接修改
55     或者利用爬蟲程序繞過前端頁面直接朝後端提交數據
56     
57     購物網站    
58         選取了貨物以後 會計算一個價格發送給後端 若是後端不作價格的校驗
59         
60         實際是獲取到用戶選擇的全部商品的主鍵值
61         而後在後端查詢出全部商品的價格 再次計算一遍
62         若是跟前端一致 那麼完成支付若是不一致直接拒絕
63 """

基本使用

 1 from django import forms
 2 
 3 
 4 class MyForm(forms.Form):
 5     # username字符串類型最小3位最大8位
 6     username = forms.CharField(min_length=3,max_length=8)
 7     # password字符串類型最小3位最大8位
 8     password = forms.CharField(min_length=3,max_length=8)
 9     # email字段必須符合郵箱格式  xxx@xx.com
10     email = forms.EmailField()

校驗數據

 1 """
 2 1.測試環境的準備 能夠本身拷貝代碼準備
 3 2.其實在pycharm裏面已經幫你準備一個測試環境
 4     python console
 5 """
 6 from app01 import views
 7 # 1 將帶校驗的數據組織成字典的形式傳入便可
 8 form_obj = views.MyForm({'username':'jason','password':'123','email':'123'})
 9 # 2 判斷數據是否合法        注意該方法只有在全部的數據所有合法的狀況下才會返回True
10 form_obj.is_valid()
11 False
12 # 3 查看全部校驗經過的數據
13 form_obj.cleaned_data
14 {'username': 'jason', 'password': '123'}
15 # 4 查看全部不符合校驗規則以及不符合的緣由
16 form_obj.errors
17 {
18   'email': ['Enter a valid email address.']
19 }
20 # 5 校驗數據只校驗類中出現的字段 多傳不影響 多傳的字段直接忽略
21 form_obj = views.MyForm({'username':'jason','password':'123','email':'123@qq.com','hobby':'study'})
22 form_obj.is_valid()
23 True
24 # 6 校驗數據 默認狀況下 類裏面全部的字段都必須傳值
25 form_obj = views.MyForm({'username':'jason','password':'123'})
26 form_obj.is_valid()
27 False
28 """
29 也就意味着校驗數據的時候 默認狀況下數據能夠多傳可是毫不可能少傳
30 """

渲染標籤

"""
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='用戶名')
"""

展現提示信息

 1 """
 2 瀏覽器會自動幫你校驗數據 可是前端的校驗弱不由風
 3 如何讓瀏覽器不作校驗
 4     <form action="" method="post" novalidate>
 5 """
 6 def index(request):
 7     # 1 先產生一個空對象
 8     form_obj = MyForm()
 9     if request.method == 'POST':
10         # 獲取用戶數據而且校驗
11         """
12         1.數據獲取繁瑣
13         2.校驗數據須要構形成字典的格式傳入才行
14         ps:可是request.POST能夠當作就是一個字典
15         """
16         # 3.校驗數據
17         form_obj = MyForm(request.POST)
18         # 4.判斷數據是否合法
19         if form_obj.is_valid():
20             # 5.若是合法 操做數據庫存儲數據
21             return HttpResponse('OK')
22         # 5.不合法 有錯誤
23     # 2 直接將該空對象傳遞給html頁面
24     return render(request,'index.html',locals())
25 
26 {% for form in form_obj %}
27         <p>
28             {{ form.label }}:{{ form }}
29             <span style="color: red">{{ form.errors.0 }}</span>
30         </p>
31 {% endfor %}
32 
33 """
34 1.必備的條件 get請求和post傳給html頁面對象變量名必須同樣
35 2.forms組件當你的數據不合法的狀況下 會保存你上次的數據 讓你基於以前的結果進行修改
36 更加的人性化
37 """
38 # 針對錯誤的提示信息還能夠本身自定製
39 class MyForm(forms.Form):
40     # username字符串類型最小3位最大8位
41     username = forms.CharField(min_length=3,max_length=8,label='用戶名',
42                                error_messages={
43                                    'min_length':'用戶名最少3位',
44                                    'max_length':'用戶名最大8位',
45                                    'required':"用戶名不能爲空"
46                                }
47                                )
48     # password字符串類型最小3位最大8位
49     password = forms.CharField(min_length=3,max_length=8,label='密碼',
50                                error_messages={
51                                    'min_length': '密碼最少3位',
52                                    'max_length': '密碼最大8位',
53                                    'required': "密碼不能爲空"
54                                }
55                                )
56     # email字段必須符合郵箱格式  xxx@xx.com
57     email = forms.EmailField(label='郵箱',
58                              error_messages={
59                                  'invalid':'郵箱格式不正確',
60                                  'required': "郵箱不能爲空"
61                              }
62                              )

鉤子函數(HOOK)

 1 """
 2 在特定的節點自動觸發完成響應操做
 3 
 4 鉤子函數在forms組件中就相似於第二道關卡,可以讓咱們自定義校驗規則
 5 
 6 在forms組件中有兩類鉤子
 7     1.局部鉤子
 8         當你須要給單個字段增長校驗規則的時候可使用
 9     2.全局鉤子
10       當你須要給多個字段增長校驗規則的時候可使用
11 """
12 # 實際案例
13 
14 # 1.校驗用戶名中不能含有666                只是校驗username字段  局部鉤子
15 
16 # 2.校驗密碼和確認密碼是否一致            password confirm兩個字段    全局鉤子
17 
18 # 鉤子函數  在類裏面書寫方法便可
19     # 局部鉤子
20     def clean_username(self):
21         # 獲取到用戶名
22         username = self.cleaned_data.get('username')
23         if '666' in username:
24             # 提示前端展現錯誤信息
25             self.add_error('username','光喊666是不行滴~')
26         # 將鉤子函數鉤去出來數據再放回去
27         return username
28 
29     # 全局鉤子
30     def clean(self):
31         password = self.cleaned_data.get('password')
32         confirm_password = self.cleaned_data.get('confirm_password')
33         if not confirm_password == password:
34             self.add_error('confirm_password','兩次密碼不一致')
35         # 將鉤子函數鉤出來數據再放回去
36         return self.cleaned_data

forms組件其餘參數及補充知識點

label                 給字段起名
error_messages  自定義報錯信息
initial                 設定默認值
required             控制字段是否必填
"""
1.字段沒有樣式
2.針對不一樣類型的input如何修改
    text
    password
    date
    radio
    checkbox
    ...
"""
widget=forms.widgets.PasswordInput(attrs={'class':'form-control c1 c2', 'username': 'jason'})
# 多個屬性值的話 直接空格隔開便可

# 第一道關卡里面還支持正則校驗
from django.core.validators import RegexValidator   # 導入RegexValidator校驗器模塊
 
class MyForm(Form):
    user = fields.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')],
    )

其餘類型渲染

 1 # radio
 2     gender = forms.ChoiceField(
 3         choices=((1, ""), (2, ""), (3, "保密")),
 4         label="性別",
 5         initial=3,
 6         widget=forms.widgets.RadioSelect()
 7     )
 8     # 單選select
 9     hobby = forms.ChoiceField(
10         choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
11         label="愛好",
12         initial=3,
13         widget=forms.widgets.Select()
14     )
15     # 多選Select
16     hobby1 = forms.MultipleChoiceField(
17         choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
18         label="愛好",
19         initial=[1, 3],
20         widget=forms.widgets.SelectMultiple()
21     )
22     # 單選checkbox
23     keep = forms.ChoiceField(
24         label="是否記住密碼",
25         initial="checked",
26         widget=forms.widgets.CheckboxInput()
27     )
28     # 多選checkbox
29     hobby2 = forms.MultipleChoiceField(
30         choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
31         label="愛好",
32         initial=[1, 3],
33         widget=forms.widgets.CheckboxSelectMultiple()
34     )

今日考題

"""
今日考題
1.簡述自定義分頁器的使用
2.forms組件是幹什麼用的,它的主要功能有哪些功能,你可否具體說說每一個功能下都有哪些常常用到的方法及注意事項(越詳細越好)
3..forms組件鉤子函數是幹什麼用的,如何編寫,請舉例說明,除此以外forms組件還提供了哪些校驗方法
"""

今日內容回顧

自定義分頁器的使用

 1 """
 2 當你在項目中須要使用第三方的功能代碼或者本身封裝的一些功能代碼
 3 那麼通常狀況下都是會新建一個文件夾(utils)專門用來存儲相關的代碼
 4     該文件夾既能夠建在全局 也能夠在每一個應用下都建立屬於該應用獨有的
 5     
 6 封裝代碼的思路
 7     1.先用最粗燥的代碼完成功能
 8     2.在功能完成的基礎之上再去考慮優化
 9         1.先由麪條版封裝成函數
10         2.再看看能不能封裝成面向對象
11         並非說必定須要封裝成面向對象的形式 要看狀況
12 """
13 # 代碼無需掌握直接拷貝使用便可
14 # 後端使用
15   book_queryset = models.Book.objects.all()  # 惰性查詢
16   current_page = request.GET.get('page',1)
17   all_count = book_queryset.count()
18   page_obj = Pagenation(current_page=current_page,all_count=all_count)
19   page_queryset = book_queryset[page_obj.start:page_obj.end]
20   # 只須要將page_obj,page_queryset傳遞給html頁面便可
21   
22 # 前端使用(自定義分頁器須要使用bootstrap)
23     {{ page_obj.page_html|safe }}
自定義分頁器

forms組件

 1 """
 2 1.渲染標籤
 3 2.校驗數據
 4 3.展現信息
 5 """
 6 from django import forms
 7 class MyForm(forms.Form):
 8   username = forms.CharField(label='用戶名',max_length=8,min_length=3)
 9 
10 # 校驗數據
11 # 1 給類傳字典
12 form_obj = MyForm({'username':'jason'})
13 # 2 判讀數據是否合法
14 form_obj.is_valid()  # 只有全部的數據都符合條件纔會爲True
15 # 3 如何查看符合條件數據
16 form_obj.cleaned_data
17 # 4 如何查看不符合條件的以及緣由
18 form_obj.errors
19 # 5 forms類中全部的字段默認都是必填的 
20 # 6 校驗的數據能夠多傳可是不能少傳
21 
22 # 渲染標籤
23 # 1 第一種
24 {{ form_obj.as_p }}
25 # 2 第二種
26 {{form_obj.username.label}}{{form_obj.username}}
27 # 3 第三種(經常使用)
28 {% for form in form_obj %}
29     {{ form.label }}:{{ form }}
30   <span>{{ form.errors.0 }}</span>
31 {% endfor  %}
32 
33 
34 # 展現錯誤信息
35 {% for form in form_obj %}
36     {{ form.label }}:{{ form }}
37   <span>{{ form.errors.0 }}</span>
38 {% endfor  %}
39 
40 username = forms.CharField(label='用戶名',
41                            max_length=8,
42                            min_length=3,
43                            error_messages={
44                              'required':"用戶名必填",
45                              ...
46                            }
47                    
48                       )
forms組件

鉤子函數

 1 """
 2 局部鉤子
 3     校驗單個字段
 4 全局鉤子
 5     校驗多個字段
 6 """
 7 def clean_username(self):
 8   self.add_error('username','用戶名錯誤')
 9   return username
10 
11 def clean(self):
12   return self.cleaned_data
鉤子函數

forms組件的重要參數

 1 label   別名
 2 min_length  最短
 3 max_length  最長
 4 required   能不能爲空
 5 initial   默認值
 6 error_messages  錯誤提示
 7 validators    正則
 8 widget  
 9 """
10 針對字段的校驗有不少種
11     1.最簡單的min_length
12     2.正則validator
13     3.鉤子函數
14 
15 前端的校驗的無關緊要 可是後端的校驗一點都不能含糊
16 
17 form表單如何取消瀏覽器自動校驗功能
18     <form novalidate></form>
19 """
forms組件的重要參數

forms其餘字段

1 """
2 radio
3 checkbox
4 select
5 瞭解整理到博客中 以後使用再來拷貝
6 https://www.cnblogs.com/Dominic-Ji/p/9240365.html
7 """
forms組件的其餘字段

做業

"""
1.整理今日內容到博客
2.利用forms組件完成用戶註冊完整功能
"""

 

 

 

""" 1.整理今日內容到博客 2.利用forms組件完成用戶註冊完整功能 """數據庫

相關文章
相關標籤/搜索