Django进阶篇(一)

时间:2021-03-22 18:05:28

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"}),
}

上面都是简单的整体的整理下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   #不合法,返回错误信息

Django进阶篇(一)

改成as_data()后只显示一个字符串格式

error_msg = user_input_obj.errors.as_data()   #不合法,返回错误信息

Django进阶篇(一)

修改方法:

1、定义

Django进阶篇(一)

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

由于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 == "":
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