Django進階篇(一)


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>
form.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})
account.py

點擊代碼

上面的只是實現最簡易的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>
form1.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"}))
forms.py

點擊代碼

擴展: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"}),
        }
View Code

 上面都是簡單的整體的整理下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>
index.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})
views.py

  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
View Code

 

由於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,默認修改之后才保存(默認)
配置 session.py
 使用
 
    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>
html
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/")
views

 

 

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))
view.py
<!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>
text.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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM