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   #不合法,返回错误信息

改成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

由于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

Django进阶篇(一)的更多相关文章

  1. 02:Django进阶篇

    目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...

  2. Django进阶篇【1】

    注:本篇是Django进阶篇章,适合人群:有Django基础,关于Django基础篇,将在下一章节中补充! 首先我们一起了解下Django整个请求生命周期: Django 请求流程,生命周期: 路由部 ...

  3. django 进阶篇

    models(模型) 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetLi ...

  4. python Django 进阶篇

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  5. Python之路【第十七篇】Django进阶篇

    规范 确立规范的好处: 代码可读性高 方便代码的定位极其查找 为以后代码扩容带来便利 场景: 在多个APP的场景下,单个app的URL函数功能较多的时候,我们可以通过以下方法来解决. 把Views写成 ...

  6. django进阶篇

    原文连接:http://www.cnblogs.com/wupeiqi/articles/5246483.html Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创 ...

  7. Python学习-day20 django进阶篇

    Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...

  8. Django进阶篇(二)

    中间件 解析 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后, django会根据自己的规则在合适的时机执行中间件中相应的方法. 在dja ...

  9. Python之路【第十六篇续】Django进阶篇

    Django请求生命周期 首先:对于所有的web框架来说本质就是一个socket服务端,浏览器是socket客户端 路由系统 在Django的urls中我们可以根据一个URL对应一个函数名来定义路由规 ...

随机推荐

  1. 1427. SMS

    http://acm.timus.ru/problem.aspx?space=1&num=1427 没想到这道题错了N遍  细节很重要呀 代码: #include<iostream> ...

  2. 去掉安卓中activity的标题栏

    去掉所有Activity界面的标题栏 修改AndroidManifest.xml 在application 标签中添加android:theme="@android:style/Theme. ...

  3. 工厂方法(factory method)

    动机(Motivation) 在软件系统中,经常面临着“某个对象”的创建工作:由需求的变化,这个对象经常面临着剧烈的变化,但是它却拥有比较稳定的接口.如何应对这种变化?如何提供一种“封装机制”来隔离出 ...

  4. Data storage on the batch layer

    4.1 Storage requirements for the master dataset To determine the requirements for data storage, you ...

  5. 关于CSS reset

    关于CSS resetCSS reset(css重置)基本上是不需要的,至少可以说80%的的CSS reset都是没有必要的,反而增加了页面CSS 的overwrite,尤其像开心网*{margin: ...

  6. C++ Primer----智能指针类 2

    指针带给了 C++巨大的灵活性,然而同样也带来无数的问题,悬挂指针,内存泄漏等. int *pInt = new int(1); // Do not forget delete pInt; 智能指针就 ...

  7. 从零开始学习Node.js例子七 发送HTTP客户端请求并显示响应结果

    wget.js:发送HTTP客户端请求并显示响应的各种结果 options对象描述了将要发出的请求.data事件在数据到达时被触发,error事件在发生错误时被触发.HTTP请求中的数据格式通过MIM ...

  8. asp.net将页面内容按需导入Excel,并设置excel样式,下载文件(解决打开格式与扩展名指定的格式不统一的问题)

    //请求一个excel类 Microsoft.Office.Interop.Excel.ApplicationClass excel = null; //创建 Workbook对象 Microsoft ...

  9. PAT (Basic Level) Practise:1012. 数字分类

    [题目链接] 给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字: A1 = 能被5整除的数字中所有偶数的和: A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3- ...

  10. ipython

    ipython 是一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数. T ...