Django以內置組件

Django組件介紹html

        分頁器的使用前端

        Formpython

        modelFormgit

        ormweb

        cookie和sessionajax

        中間件sql

        信號數據庫

 

1.分頁器的使用django

分頁器在頁面中很是常見,當數據庫條數數據過多時,頁面一次性顯示很差看,咱們就可使用頁面器,將數據分幾回顯示後端

一個簡單的分頁功能,能夠導入用

  page_num = request.GET.get('page','1')
    try:
        page_num = int(page_num)
        if page_num <=0:
            page_num = 1
    except Exception as e:
        page_num =1
    #總數量
    all_count = len(userlist)
    #每頁顯示爲10 頁
    per_num = 10
    #總頁碼數
    total_page_num, more =divmod(all_count,per_num)
    if more:
        total_page_num += 1
    #最多顯示的頁面數
    max_show = 11
    half_show = max_show//2
    if total_page_num < max_show:
        page_start = 1
        page_end = total_page_num
    elif page_num <= half_show:
        page_start =1
        page_end =max_show
    elif page_num + half_show > total_page_num:
        page_start = total_page_num-max_show +1
        page_end = total_page_num
    else:
        #起始頁面
        page_start = page_num - half_show
        #終止頁面
        page_end = page_num + half_show
    start =(page_num-1) * per_num
    end =page_num*per_num

    page_list = []

    if page_num == 1:
        page_list.append('<li class="disabled"><a>上一頁</a></li>')
    else:
        page_list.append('<li ><a href="?page={}">上一頁</a></li>'.format(page_num - 1))

    for i in range(page_start, page_end + 1):
        if i == page_num:
            page_list.append('<li class="active" ><a href="?page={}">{}</a></li>'.format(i, i))
        else:
            page_list.append('<li><a href="?page={}">{}</a></li>'.format(i, i))
        if page_num == total_page_num:
            page_list.append('<li class="disabled"><a>下一頁</a></li>')
        else:
            page_list.append('<li><a href="?page={}">下一頁</a></li>'.format(page_num + 1))

        page_html = ''.join(page_list)

        return render(request, 'user_list.html',
                      {'users': userlist[start:end], 'page_html': page_html})
分頁

2.Form組件

django框架提供了一個form類,來處理web開發中的表單相關事項.form最常作的是對用戶輸入的內容進行驗證,爲此django的forms類提供了全面的內容驗證和保留用戶上次輸入數據的支持

form組件的兩大功能:

   ---對用戶提交的內容進行驗證(from表單/ajax)

   ---表留用戶上次輸入的內容

form組件的幾大用處:

1.校驗字段功能

1.首先先到導入forms這個模塊
from django import forms
2.本身寫一個類,並繼承forms.Form
class Myform(forms.Form):
    #這行代碼的意思,name這字段最長爲8,最短爲3
    name=forms.charField(max_length=8)

def index(request):
    dic={'name':'zh'}
    #這裏就是類的實例化,傳的參數必須爲一個字典
    myform =Myform(dic)
    #這是對象的綁定方式,它的返回值就是一個布爾值
    # True表示你傳的dic這個字典知足form裏的條件,False就是不知足
    # 咱們能夠經過判斷它,再進行邏輯操做,好比該字段符合你的要求,再怎麼操做
    if myform.is_valid():
        return HttpResponse('校驗成功')
    # 走到這一步,表明當中有字段不符合要求
        # 它的返回值是一個對象,可是它繼承了字典,因此你能夠經過get取到錯誤提示
        # 對了,你傳的字典的key值必需要和建立的類(Myform)要對應,而且只能多,不能少
        # name_error = myform.errors.get('name')
        # 這樣你能夠取到name字段出錯的緣由了
        name_error=myform.errors
        return HttpResponse('校驗失敗')
## 總結下:一、Myform的實例化必須傳字典
              2、is_valid()返回值是布爾類型
              三、errors  調用這個方法,返回值是對象,你能夠經過get取值
例子

2.渲染標籤功能

form組件能夠在視圖函數中使用,也能夠在模板中使用

   渲染方式一:
    <form action='' method='post'>
        用戶名:{{myform:name}} <br>
        <input type='submit' value = '提交'></input>
    </form>
    # 這裏的{{myform:name}} 和你寫input框是同樣的效果,就是屬性比input框多一點

    渲染方式二(推薦使用):
    <form action='' method='post'>
        {% for foo in myform%}
            {{ foo.lable }} : {{ foo }}  <br>
        <input type='submit' value = '提交'></input>
    </form>
    # 頁面顯示都是同樣的,foo.lable不是用戶名,是name,可是你能夠在建立Myform類時
    # 在CharFiel中添加lable='用戶名',這樣就好了。

    渲染方式三:
        <form action='' method='post'>
            {{ myform.as_p }}
        <input type='submit' value = '提交'></input>
    </form>
    # 對,方式三就是這麼簡單,可是拓展性太差了,對不對,因此不推薦使用它
例子

3.渲染錯誤信息功能

 渲染錯誤信息,以前不是寫了error這個方法嘛,他就是裝着錯誤信息的對象,
    其實就是讓它渲染到頁面上,這不就是很簡單嘛
    拿渲染方式二來舉例子吧:
    <form action='' method='post'>
        {% for foo in myform%}
            {{ foo.lable }} : {{ foo }} <span>{{foo.errors.0}}</span><br>
        <input type='submit' value = '提交'></input>
    </form>

    # 來說下爲何不是用get去取錯誤信息,首先這個foo是什麼?它就是你建立的字段
    # 因此直接經過索引取值就行了,那麼就應該知道foo.errors貌似就是一個列表對吧
    # 模板渲染時我在後臺渲染好了,再返回到前臺的,那我能夠不能夠將錯誤信息傳到前臺
    # 讓前臺執行DOM操做進行渲染呢?
    # 我以爲太麻煩,何況前端我。。。(你懂的)
例子

4.組件的參數配置

  其實在些Myform,下面的字段還有不少參數,我就寫寫大概有什麼用
    max_length    # 表明該字段最長爲多少
    min_length    # 表明該字段最短爲多少
    error_messages # 這是設置錯誤信息的屬性
    # 例子
    error_messages=
    {'max_length': '最長八位', 'min_length': '最短三位', 'required': '不能爲空'}
    required   # 默認值爲True,意思是你傳來的字段必須有它,沒有的話校驗失敗
    widget=widgets.TextInput()  # 你在模板渲染的時候,就會渲染成Input框,type爲text
                                  還有其餘類型的input框,本身在看看吧
    對了,在TextInput(),你能夠爲input添加屬性,attrs={'class':'abc'}  寫在括號裏面
    lable   #這個是否是上面講到了,lable='用戶名'
例子

5.鉤子

局部鉤子
    局部鉤子說白了就是寫一個函數,可是這個函數名必須爲clean_name,這個name是能夠改變的,
    你定義的類裏,你想對哪一個字段寫鉤子函數,這個name就爲那個字段的名字,好比我想爲password這個
    字段寫鉤子函數,那函數名就爲clean_password,就這樣。

    那這個局部鉤子有什麼用了?
        首先你的程序能走到局部鉤子這一步,就說明你傳的字典中的字段符合要求,這要記清楚,那麼咱們在
        取值就從clean_data中取就行了,clean_data裏裝的是符合要求的數據,是一個字典。
        咱們能夠從clean_data中取到相應的值再作一次邏輯處理,好比我寫clean_name這個局部鉤子,
        我能夠拿到name,對這個name進行一些操做,名字開頭不能是數字,名字中不能有有什麼字符,這
        些等等,看你本身的需求,邏輯代碼寫好了,最後return name 就行了
        
全局鉤子
    全局鉤子其實做用差很少的,每一個字段你能夠進行局部鉤子進行邏輯書寫,這些處理完成以後,有須要的話,
    你再進行全局處理,舉個例子就大概能明白,你在寫註冊用戶的時候,是否是有密碼,確認密碼,你能夠進行
    佈局鉤子處理,處理完畢是否是在進行判斷,判斷他們是否相等,相等的話,就存到數據庫中,不相等就拋個
    異常,對了對了,上面局部鉤子忘記寫異常,下面講講。
    

-----1、局部鉤子,全局鉤子所拋出異常的類型爲ValidationError,它是在下面這行代碼導入
        from django.core.exceptions import ValidationError
     2、局部鉤子拋出的異常會添加到該字段中的錯誤信息中,也就是myform.errors.get(字段名)中
     三、而全局鉤子拋出的異常會添加到__all__中,myform.errors.get('__all__')中能夠取到
     
說明

3.ModelForm

做用:

1.手動對單表進行增,刪,改,查,手動把orm操做獲取的數據渲染到模塊;(階段1)

2.Form組件(類),自動生成標籤(input,select),並對用戶輸入的數據作規則驗證;(階段2)

3.ModelForm顧名思義就Form和Django的Model數據庫模型結合體,能夠簡單,方便地對數據庫進行增長,編輯操做和驗證標籤的生成

使用ModelForm

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{{ form_obj.as_p }}
{#<p>姓名:{{form_obj.name  }}</p>#}
</body>
</html>
前端
class BSForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for filed in self.fields.values():
            if not isinstance(filed, forms.BooleanField):
                filed.widget.attrs.update({'class': "form-control"})

class RegForm(BSForm):
    re_pwd = forms.CharField(widget=forms.PasswordInput, label='確認密碼')
    class Meta:
        model = models.UserProfile
        fields='__all__'                      #獲取所有的
        exclude=['memo','is_active']         #刪除不想要的
        labels = {
            'username': '用戶名'                 #標籤
        }
        widgets = {
            'password': forms.PasswordInput(attrs={'class': "form-control", 'k1': 'v1'}),
        }
        error_messages = {
            'password': {
                'required': '必填的'
            }
        }
    def clean(self):
        pwd = self.cleaned_data.get('password', '')
        re_pwd = self.cleaned_data.get('re_pwd', '')
        if pwd == re_pwd:
            return self.cleaned_data
        self.add_error('re_pwd', '兩次密碼不一致')

        raise ValidationError('兩次密碼不一直')


def reg(request):
    form_obj=RegForm()
    if request.method =="POST":
        form_obj=RegForm(request.POST)
        if form_obj.is_valid():
            # print(form_obj.cleaned_data)
            # form_obj.cleaned_data.pop('re_pwd')
            # models.UserProfile.objects.create(**form_obj.cleaned_data)
            form_obj.save()
            return  redirect(reverse('login'))
    return render(request,'reg.html',{'form_obj':form_obj})
後端

4.orm

--MVC框架中包括一個重要的部分,就是ORM,它實現了數據模型與數據庫的解耦,即數據模型的設計不須要依賴於特定的數據庫,經過簡單的配置就能夠輕鬆更換數據庫

--ORM是'對象-關係-映射'的簡稱 ,主要任務是:

  *根據對象的類型生成表結構

  *將對象,列表的操做,轉換爲sql語句

  *將sql查詢到的結果轉換爲對象,列表

--這極大地減輕了開發人員的工做量,不須要面對因數據庫變動而致使的無效勞動

--Django中的模型包含存儲數據的字段和約束,對應着數據庫中惟一的表

1.在models.py中定義模型類,要求繼承自models.Model
2.把應用加入settings.py文件的installed_app項
3.生成遷移文件
4.執行遷移生成表
5.使用模型類進行crud操做
開發流程
在模型中定義屬性,會生成表中的字段
django根據屬性的類型肯定如下信息:
    當前選擇的數據庫支持字段的類型
    渲染管理表單時使用的默認html控件
    在管理站點最低限度的驗證
django會爲表增長自動增加的主鍵列,每一個模型只能有一個主鍵列,若是使用選項設置某屬性爲主鍵列後,則django不會再生成默認的主鍵列
屬性命名限制
    不能是python的保留關鍵字
    因爲django的查詢方式,不容許使用連續的下劃線
定義模型
定義屬性時,須要字段類型
字段類型被定義在django.db.models.fields目錄下,爲了方便使用,被導入到django.db.models中
使用方式
導入from django.db import models
經過models.Field建立字段類型的對象,賦值給屬性
對於重要數據都作邏輯刪除,不作物理刪除,實現方法是定義isDelete屬性,類型爲BooleanField,默認值爲False
字段類型
AutoField:一個根據實際ID自動增加的IntegerField,一般不指定
若是不指定,一個主鍵字段將自動添加到模型中
BooleanField:true/false 字段,此字段的默認表單控制是CheckboxInput
NullBooleanField:支持null、true、false三種值
CharField(max_length=字符長度):字符串,默認的表單樣式是 TextInput
TextField:大文本字段,通常超過4000使用,默認的表單控件是Textarea
IntegerField:整數
DecimalField(max_digits=None, decimal_places=None):使用python的Decimal實例表示的十進制浮點數
DecimalField.max_digits:位數總數
DecimalField.decimal_places:小數點後的數字位數
FloatField:用Python的float實例來表示的浮點數
DateField[auto_now=False, auto_now_add=False]):使用Python的datetime.date實例表示的日期
參數DateField.auto_now:每次保存對象時,自動設置該字段爲當前時間,用於"最後一次修改"的時間戳,它老是使用當前日期,默認爲false
參數DateField.auto_now_add:當對象第一次被建立時自動設置當前時間,用於建立的時間戳,它老是使用當前日期,默認爲false
該字段默認對應的表單控件是一個TextInput. 在管理員站點添加了一個JavaScript寫的日曆控件,和一個「Today"的快捷按鈕,包含了一個額外的invalid_date錯誤消息鍵
auto_now_add, auto_now, and default 這些設置是相互排斥的,他們之間的任何組合將會發生錯誤的結果
TimeField:使用Python的datetime.time實例表示的時間,參數同DateField
DateTimeField:使用Python的datetime.datetime實例表示的日期和時間,參數同DateField
FileField:一個上傳文件的字段
ImageField:繼承了FileField的全部屬性和方法,但對上傳的對象進行校驗,確保它是個有效的image
字段選項
經過字段選項,能夠實現對字段的約束
在字段對象時經過關鍵字參數指定
null:若是爲True,Django 將空值以NULL 存儲到數據庫中,默認值是 False
blank:若是爲True,則該字段容許爲空白,默認值是 False
對比:null是數據庫範疇的概念,blank是表單驗證證範疇的
db_column:字段的名稱,若是未指定,則使用屬性的名稱
db_index:若值爲 True, 則在表中會爲此字段建立索引
default:默認值
primary_key:若爲 True, 則該字段會成爲模型的主鍵字段
unique:若是爲 True, 這個字段在表中必須有惟一值
關係
關係的類型包括
ForeignKey:一對多,將字段定義在多的端中
ManyToManyField:多對多,將字段定義在兩端中
OneToOneField:一對一,將字段定義在任意一端中
能夠維護遞歸的關聯關係,使用'self'指定,詳見「自關聯」
用一訪問多:對象.模型類小寫_set
定義屬性
增:
 models.UserInfo.object.create(name=new_name)
刪:
models.UserInfo.object.get(id=xxx,None)
models.delete()
改:
obj = models.UserInfo.object.get(id=xx,None)
obj = new_xxx
obj.save()  #至關於修改後提交數據
查
querylist=models.Entry.objects.all()
print([e.title for e in querylist])
print([e.title for e in querylist])

entry = models.Entry.objects.get(id=?)
orm操做

5.cookie和session

cookies是瀏覽器爲web服務器存儲的一個信息,每次瀏覽器從某個服務器請求頁面時,都會自動帶上之前收到的cookie.cookie保存在客戶端,安全性較差,注意不要保存沒敢信息.

  --網絡登陸

  --購物車

def login(request):
    if request.method == 'GET':
        return render(request,'login2.html')

    if request.method == 'POST':
        u = request.POST.get('username')
        p = request.POST.get('pwd')
        dic = user_info.get(u)

        if not  dic:
            return  render(request,'login2.html')

        current_date = datetime.datetime.utcnow()

        current_date = current_date + datetime.timedelta(seconds=10)
        if dic['pwd'] == p:
            res = redirect('/myapp/index')
            # res.set_cookie('username',u,max_age=10)
#對cookie設置了超時時間和安全設置          
res.set_cookie('username',u,expires=current_date,httponly=True)
            # res.set_signed_cookie('username',u,salt="121221")
            return res
        else:
            return  render(request,'login2.html')
登陸頁面

詳情頁面,若是cookie 驗證經過則進入index頁面,不然刷新進入登陸頁面

def auth(func):
    def inner(request,*args,**kwargs):
        v = request.COOKIES.get('username')
        if not v:
            return redirect('/myapp/login')
        return func(request,*args,**kwargs)

    return inner
@auth
def index(request):

    v = request.COOKIES.get('username')

    return render(request,'index2.html',{'current_user':v})
驗證

session就是保存在後臺數據或者緩存中的一個鍵值對,一樣的存儲着用戶信息,爲更好的保護用戶隱私,實際上是對前端cookie的一個升級的保護措施

當登陸成功後,會向後臺數據庫 與 前端 Cookie同時發放一段隨機字符串,分別保存在後臺的session中,前端 寫到用戶瀏覽器中,用戶下次登陸時候 拿着瀏覽器存着的sessionID當作KEY去後臺數據庫中匹配進行驗證登陸便可拿到用戶相關信息,能夠防止敏感信息直接暴露在瀏覽器上

做者:TianTianBaby223
連接:https://www.jianshu.com/p/a2d696364501
來源:簡書
簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
實現原理

Django下用session實現登陸驗證

def sessionLogin(request):
    if request.method == "GET":
        return render(request,'sessionLogin.html')

    elif request.method == "POST":
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        if user == 'root' and pwd =="123":
            #生成隨機字符串
            #寫到用戶瀏覽器
            #保存到session中
            #在隨機字符串對應的字典中設置相關內容...
            request.session['username'] = user
            request.session['is_login'] = True
            if request.POST.get('rmb',None) == '1':
                request.session.set_expiry(10)

            return redirect('/myapp/sessionindex')
        else:
            return render(request, 'sessionLogin.html')

詳情頁邏輯

def sessionindex(request):
    #獲取當前用戶的隨機字符串
    #根據隨機字符串獲取對應信息
    if request.session.get('is_login',None):
        return render(request,'sessionindex.html',{'username':request.session['username']})
    else:
        return HttpResponse('get out')

6.中間件

定義:介於request(請求)與response(響應)處理之間的一道處理過程,相對比較輕量級,位於web服務端與url路由層之間

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',  #一些安全設置,好比xss腳本過濾
    'django.contrib.sessions.middleware.SessionMiddleware',#session支持中間件,加入這個中間件,會在數據庫中生成一個django_session的表。
    'django.middleware.common.CommonMiddleware',   #通用中間件,會處理一些url
    'django.middleware.csrf.CsrfViewMiddleware',   #跨域請求僞造中間件,加入這個中間件,在提交表單的時候會必須加入csrf_token,cookie中也會生成一個名叫csrftoken的值,也會在header中加入一個HTTP_X_CSRFTOKEN的值來放置CSRF攻擊。
    'django.contrib.auth.middleware.AuthenticationMiddleware',  #用戶受權中間件。他會在每一個HttpRequest對象到達view以前添加當前登陸用戶的user屬性,也就是你能夠在view中經過request訪問user。
    'django.contrib.messages.middleware.MessageMiddleware',#消息中間件。展現一些後臺信息給前端頁面。若是須要用到消息,還須要在INSTALLED_APPS中添加django.contrib.message纔能有效。若是不須要,能夠把這兩個都刪除。
    'django.middleware.clickjacking.XFrameOptionsMiddleware',#防止經過瀏覽器頁面跨Frame出現clickjacking(欺騙點擊)攻擊出現。
    'A_orm.middlewares.auth.AuthenticationMiddleware',
]
內置中間件

請求進來是自上而下,經過反射找到類,用for循環來執行,能夠自定義中間件,但也要寫入MIDDLEWAR

1、process_request(self,request)
#請求完執行

2、process_view(self, request, callback, callback_args, callback_kwargs)
#若是有返回值,跳轉到最後一箇中間件,執行最後一箇中間件的response方法,逐步返回
3、process_template_response(self,request,response)
#默認不執行,只有在視圖函數的返回對象中有render方法纔會執行
4、process_exception(self, request, exception)
#默認啥也不執行,在視圖函數出現錯誤是才執行,返回錯誤信息
5、process_response(self, request, response)
#響應執行
自定義中間件
1、作IP限制

放在 中間件類的列表中,阻止某些IP訪問了;

2、URL訪問過濾

若是用戶訪問的是login視圖(放過)

若是訪問其餘視圖(須要檢測是否是有session已經有了放行,沒有返回login),這樣就免得在 多個視圖函數上寫裝飾器了!

3、緩存(還記得CDN嗎?)

客戶端請求來了,中間件去緩存看看有沒有數據,有直接返回給用戶,沒有再去邏輯層 執行視圖函數
應用場景

執行順序:

1.咱們要在app01文件下建立一個文件(middlewares)文件,在下面建立一個.py文件寫入自定義中間件

2.在setting裏面添加中間件,文件路徑+功能

3.在views.py大家調用便可.

def index(request):
    print('1')

7.信號

定義:用於框架執行操做時解耦,就是一些動做發生的時候,信號容許特定的發送者去提醒一些接受者

Model signals
    pre_init                    # django的model執行其構造方法前,自動觸發
    post_init                   # django的model執行其構造方法後,自動觸發
    pre_save                    # django的model對象保存前,自動觸發
    post_save                   # django的model對象保存後,自動觸發
    pre_delete                  # django的model對象刪除前,自動觸發
    post_delete                 # django的model對象刪除後,自動觸發
    m2m_changed                 # django的model中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發
    class_prepared              # 程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
內置信號
Management signals
    pre_migrate                 # 執行migrate命令前,自動觸發
    post_migrate                # 執行migrate命令後,自動觸發
數據庫遷移的時候信號
Request/response signals
    request_started             # 請求到來前,自動觸發
    request_finished            # 請求結束後,自動觸發
    got_request_exception       # 請求異常後,自動觸發
from django.core.signals import request_finished
from django.core.signals import request_started
請求和響應的信號
setting_changed             # 使用test測試修改配置文件時,自動觸發
template_rendered           # 使用test測試渲染模板時,自動觸發
from django.test.signals import setting_changed
from django.test.signals import template_rendered
Test signals
connection_created          # 建立數據庫鏈接時,自動觸發
from django.db.backends.signals import connection_created
Database Wrappers
相關文章
相關標籤/搜索