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>
 
# !/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})
上面的只是实现最简易的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>
 
#!/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"}))
扩展: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"}), }
上面都是简单的整体的整理下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>
 
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})
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
由于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,默认修改之后才保存(默认)
 
使用 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>
 
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/")
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))
 
<!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>
更多: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
 
         
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号