琪齐

空想终日彷徨行动方可无惧!

导航

Django进阶篇(一)

Posted on 2016-08-29 09:15  琪齐  阅读(1767)  评论(0编辑  收藏  举报

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