Form+分页+Session+Ajax+csrf+中间件+Admin
7、Model连表操作
一对多和一对一之间多表查询
如下表结构:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class UserType(models.Model): name = models.CharField(max_length=50)class UserInfo(models.Model): username = models.CharField(max_length=50) password = models.CharField(max_length=50) email = models.EmailField() user_type = models.ForeignKey('UserType') |
1、查看所有的用户信息(包括所属用户类型)
|
1
2
3
4
|
userObj = UserInfo.objects.all() for item in userObj: print item.name print item.user_type.name |
1.1、all、get、filter
1.2、user_type是什么?
1.3、查找所有用户类型ID大于5所对应的所有用户信息
2、查看用户类型等于 “超级管理员”的所有用户
|
1
|
models.UserInfo.objects.filter(user_type__name='超级管理员') |
|
1
2
3
4
|
UserInfo.objects.filter(user_type__name='sb')select * from UserInfo xxxxxUserInfo.objects.filter(user_type__name='sb').values('username','password')select username,password from UserInfo xxxxx |
3、查看指定映射的列
|
1
|
models.UserInfo.objects.all().values('id','user_type__name') |
多对多表之间的查询
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class UserInfo(models.Model): username = models.CharField(max_length=50) password = models.CharField(max_length=50) email = models.EmailField()class UserGroup(models.Model): GroupName = models.CharField(max_length=50) user = models.ManyToManyField('UserInfo') |
由于多对多之间会出现第三张关系表,而如果对关系表操作时,使用如下方法:
1、添加一条关系,两种方式
方式一、
|
1
2
3
4
|
u1 = models.UserInfo.objects.get(id=1)g1 = models.UserGroup.objects.get(id=1)g1.user.add(u1) |
方式二、
|
1
2
3
4
|
u1 = models.UserInfo.objects.get(id=1)g1 = models.UserGroup.objects.get(id=2)u1.usergroup_set.add(g1) |
2、删除一条关系
|
1
2
3
4
|
u1 = models.UserInfo.objects.get(id=1)g1 = models.UserGroup.objects.get(id=1)g1.user.delete(u1) |
3、获取用户组等于[用户组A]的所有用户信息
|
1
2
|
gObj = models.UserGroup.objects.get(GroupName='主机组A')t = gObj.user.all() |
4、获取用户A的所属于的所有用户组
|
1
2
|
uobj = models.UserInfo.objects.get(id=1)bb = uobj.usergroup_set.all() |
注意:xx_set中的【_set】是固定搭配
http://my.oschina.net/u/572994/blog/105280
8、Form
django中的Form一般有两种功能:
- 输入html
- 验证用户输入
|
1
2
3
4
|
class ALogin(forms.Form): username = forms.CharField() email = forms.EmailField(required=True) ip = forms.IPAddressField() |
|
1
2
3
4
5
6
7
8
9
|
def Login(request): if request.method == 'POST': form = ALogin(request.POST) if form.is_valid(): data = form.cleaned_data return HttpResponse("<h1>OK</h1>"); form = ALogin() #form = AccountForm(initial={'name': 'I love your site!'}) return render_to_response('Form/Login.html',{'form': form},context_instance=RequestContext(request)) |
Form的应用
|
1
2
3
4
5
6
7
8
9
10
11
12
|
class Register(forms.Form): gender_choices = ( (1,'男'), (2,'女'), ) username = forms.CharField() gender = forms.CharField(widget=forms.widgets.Select(chioces=gender)) email = forms.EmailField(required=False) |
扩展:ModelForm
在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义
|
1
2
3
4
5
6
7
8
9
10
|
class AdminModelForm(forms.ModelForm): class Meta: model = models.Admin #fields = '__all__' fields = ('username', 'email') widgets = { 'email' : forms.PasswordInput(attrs={'class':"alex"}), } |
9、分页
分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。
1、设定每页显示数据条数
2、用户输入页码(第一页、第二页...)
3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
4、在数据表中根据起始位置取值,页面上输出数据
需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]
1、设定每页显示数据条数
2、用户输入页码(第一页、第二页...)
3、设定显示多少页号
4、获取当前数据总条数
5、根据设定显示多少页号和数据总条数计算出,总页数
6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
7、在数据表中根据起始位置取值,页面上输出数据
8、输出分页html,如:[上一页][1][2][3][4][5][下一页]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#!/usr/bin/env python# _*_coding:utf-8_*_from django.utils.safestring import mark_safeclass 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]+1def 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][下一页]
10、Cookie和Session
操作Cookie
获取cookie:request.COOKIES[key]
设置cookie:response.set_cookie(key,value)
由于cookie保存在客户端的电脑上,所以,jquery也可以操作cookie。
|
1
2
|
<script src='/static/js/jquery.cookie.js'></script>$.cookie("list_pager_num", 30,{ path: '/' }); |
操作Session
获取session:request.session[key]
设置session:reqeust.session[key] = value
删除session:del request[key]
|
1
2
3
4
5
|
request.session.set_expiry(value)* 如果value是个整数,session会在些秒数后失效。* 如果value是个datatime或timedelta,session就会在这个时间后失效。* 如果value是0,用户关闭浏览器session就会失效。* 如果value是None,session会依赖全局session失效策略。 |
更多见:http://docs.30c.org/djangobook2/chapter14/
详述Cookie和Session之间见不得人的勾当...
...
11、Ajax
|
1
2
3
4
5
6
7
8
9
10
11
|
$.ajax({ url:"/web/index/", data:{id:1,name:'alex'}, type:'POST', success:function(data){ }, error:function(){ }}); |
12、跨站请求伪造
简介
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
- @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
- @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
应用
1、普通表单
|
1
2
3
4
5
|
veiw中设置返回值: return render_to_response('Account/Login.html',data,context_instance=RequestContext(request)) html中设置Token: {% csrf_token %} |
2、Ajax
对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。
view.py
|
1
2
3
4
5
6
7
8
9
10
|
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)) |
text.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
<!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({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); 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
13、中间件
简介
django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。
在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

与mange.py在同一目录下的文件夹 wupeiqi/middleware下的auth.py文件中的Authentication类
中间件中可以定义四个方法,分别是:
- process_request(self,request)
- process_view(self, request, callback, callback_args, callback_kwargs)
- process_exception(self, request, exception)
- process_response(self, request, response)
以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

自定义中间件
1、创建中间件类
|
1
2
3
4
5
6
7
8
9
10
11
12
|
class RequestExeute(object): def process_request(self,request): pass def process_view(self, request, callback, callback_args, callback_kwargs): i =1 pass def process_exception(self, request, exception): pass def process_response(self, request, response): return response |
2、注册中间件
|
1
2
3
4
5
6
7
8
9
10
|
MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'wupeiqi.middleware.auth.RequestExeute',) |
14、admin
django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:
- 创建后台管理员
- 配置url
- 注册和配置django admin后台管理页面
1、创建后台管理员
|
1
|
python manage.py createsuperuser |
2、配置后台管理url
|
1
|
url(r'^admin/', include(admin.site.urls)) |
3、注册和配置django admin 后台管理页面
a、在admin中执行如下配置
|
1
2
3
4
5
6
7
8
|
from django.contrib import adminfrom app01 import modelsadmin.site.register(models.UserType)admin.site.register(models.UserInfo)admin.site.register(models.UserGroup)admin.site.register(models.Asset) |
b、设置数据表名称
|
1
2
3
4
5
6
|
class UserType(models.Model): name = models.CharField(max_length=50) class Meta: verbose_name = '用户类型' verbose_name_plural = '用户类型' |
c、打开表之后,设定默认显示,需要在model中作如下配置
|
1
2
3
4
5
|
class UserType(models.Model): name = models.CharField(max_length=50) def __unicode__(self): return self.name |
|
1
2
3
4
5
6
7
8
9
10
11
12
|
from django.contrib import adminfrom app01 import modelsclass 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、为数据表添加搜索功能
|
1
2
3
4
5
6
7
8
9
10
11
12
|
from django.contrib import adminfrom app01 import modelsclass 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、添加快速过滤
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
from django.contrib import adminfrom app01 import modelsclass 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://docs.30c.org/djangobook2/chapter06/

浙公网安备 33010602011771号