Django基础(二)
来源:互联网 发布:网络通信工作原理ppt 编辑:程序博客网 时间:2024/06/08 15:08
Django基础(二)
上节回顾
web程序的生命周期
MVC和MTV
路由系统和自定义动态路由
Model
模版语言 和 simple_tag
7、Model连表操作
- 指定映射
- 连表条件
- 一对一
- 多对多
class UserProfile(models.Model): user_info = models.OneToOneField('UserInfo') username = models.CharField(max_length=64) password = models.CharField(max_length=64) def __unicode__(self): return self.usernameclass UserInfo(models.Model): user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'), ) user_type = models.IntegerField(choices=user_type_choice) name = models.CharField(max_length=32) email = models.CharField(max_length=32) address = models.CharField(max_length=128) def __unicode__(self): return self.nameclass UserGroup(models.Model): caption = models.CharField(max_length=64) user_info = models.ManyToManyField('UserInfo') def __unicode__(self): return self.captionclass Host(models.Model): hostname = models.CharField(max_length=64) ip = models.GenericIPAddressField() user_group = models.ForeignKey('UserGroup') def __unicode__(self): return self.hostname
一对一
多对多表之间的查询
注意:xx_set中的【_set】是固定搭配
8、Form
django中的Form一般有两种功能:
- 输入html
- 验证用户输入
#!/usr/bin/env python# -*- coding:utf-8 -*-import refrom django import formsfrom django.core.exceptions import ValidationErrordef 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 PublishForm(forms.Form): user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'), ) user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice, attrs={'class': "form-control"})) title = forms.CharField(max_length=20, min_length=5, error_messages={'required': u'标题不能为空', 'min_length': u'标题最少为5个字符', 'max_length': u'标题最多为20个字符'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'标题5-20个字符'})) memo = forms.CharField(required=False, max_length=256, widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3})) phone = forms.CharField(validators=[mobile_validate, ], error_messages={'required': u'手机不能为空'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'手机号码'})) email = forms.EmailField(required=False, error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))Form
def publish(request): ret = {'status': False, 'data': '', 'error': '', 'summary': ''} if request.method == 'POST': request_form = PublishForm(request.POST) if request_form.is_valid(): request_dict = request_form.clean() print request_dict ret['status'] = True else: error_msg = request_form.errors.as_json() ret['error'] = json.loads(error_msg) return HttpResponse(json.dumps(ret))
扩展: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"
}),
}
9、分页
分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。
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][下一页]
10、Cookie和Session
操作Cookie
获取cookie:request.COOKIES[key]
设置cookie:response.set_cookie(key,value)
由于cookie保存在客户端的电脑上,所以,jquery也可以操作cookie。
<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]
request.session.set_expiry(value)
*
如果value是个整数,session会在些秒数后失效。
*
如果value是个datatime或timedelta,session就会在这个时间后失效。
*
如果value是
0
,用户关闭浏览器session就会失效。
*
如果value是
None
,session会依赖全局session失效策略。
更多见:http://docs.30c.org/djangobook2/chapter14/
应用
def
login(func):
def
wrap(request,
*
args,
*
*
kwargs):
# 如果未登陆,跳转到指定页面
if
request.path
=
=
'/test/'
:
return
redirect(
'http://www.baidu.com'
)
return
func(request,
*
args,
*
*
kwargs)
return
wrap
11、Ajax
$.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中设置了全局中间件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect
应用
1、普通表单
veiw中设置返回值:
return
render_to_response(
'Account/Login.html'
,data,context_instance
=
RequestContext(request))
html中设置Token:
{
%
csrf_token
%
}
2、Ajax
对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。
view.py
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
<!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、创建中间件类
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、注册中间件
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、创建后台管理员
python manage.py createsuperuser
2、配置后台管理url
url(r
'^admin/'
, include(admin.site.urls))
3、注册和配置django admin 后台管理页面
a、在admin中执行如下配置
b、设置数据表名称
class
UserType(models.Model):
name
=
models.CharField(max_length
=
50
)
class
Meta:
verbose_name
=
'用户类型'
verbose_name_plural
=
'用户类型'
c、打开表之后,设定默认显示,需要在model中作如下配置
d、为数据表添加搜索功能
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://docs.30c.org/djangobook2/chapter06/
完善主机管理系统:
- 登陆注册(利用ajax实现,使用onblur事件,检测当前用户名是否已经存在)
- 用户会话保持(Session)
- Form验证用户输入
- 自定义中间件记录请求IP(或黑名单)
- 用户管理、用户组管理、主机管理(增删改查,分页)
- 自定义页面表格行数(可选)
- Django基础(二)
- Django边学边做(二)
- django-cms(二)
- Django初探(二)
- Django学习(二)
- Django入门(二)
- Django基础(一)
- Django基础(一)
- Django点滴(二)---会话
- Django 生成PDF(二)
- django学习记录(二)
- Django学习笔记(二)
- django之todolist(二)
- python+django实践(二)
- Django官方教程(二)
- Django入门探索(二)
- Django学习笔记(二)
- Django二(MySQL数据库)
- intptr_t 其实不是指针类型
- STL/C++__中 set(集合) 删除元素
- Oh, my goddess
- 根据select选项的值,改变css
- 黑马程序员_JAVA的接口和抽象类
- Django基础(二)
- V4L2编程
- Spring+SpringMVC+mybatis+easyui整合实例(一)实例介绍
- 下拉菜单
- Myeclipse不能编译解决方案
- Apache和Httpd是什么关系
- 微信jssdk分享及验签
- Pixhawk---10月6号后固件编译由make编译系统转到cmake编译系统后
- Custom view … overrides onTouchEvent but not performClick