Django: 之Model、Cookis、Session
到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:
创建数据库,设计表结构和字段
使用MySQLdb来连接数据库,并编写数据访问层代码
业务逻辑层去调用数据访问层执行数据库操作
import MySQLdb def GetList(sql):
db = MySQLdb.connect(user='root', db='wulaoerdb', passwd='', host='localhost')
cursor = db.cursor()
cursor.execute(sql)
data = cursor.fetchall()
db.close()
return data def GetSingle(sql):
db = MySQLdb.connect(user='root', db='wulaoerdb', passwd='', host='localhost')
cursor = db.cursor()
cursor.execute(sql)
data = cursor.fetchone()
db.close()
return data
django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。
PHP: activerecord
JAVA:Hibernate
C#:Entity Framework
django中遵循Code Frist的原则,即:根据代码中定义的泪来自动生成数据库表。
一、创建表
1、基本结构
from django.db import models class userinfo(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField()
memo = models.TextField()
、models.AutoField 自增列 = int()
如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
、models.CharField 字符串字段
必须 max_length 参数
、models.BooleanField 布尔类型=tinyint()
不能为空,Blank=True
、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar
继承CharField,所以必须 max_lenght 参数
、models.DateField 日期类型 date
对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
、models.DateTimeField 日期类型 datetime
同DateField的参数
、models.Decimal 十进制小数类型 = decimal
必须指定整数位max_digits和小数位decimal_places
、models.EmailField 字符串类型(正则表达式邮箱) =varchar
对字符串进行正则表达式
、models.FloatField 浮点类型 = double
、models.IntegerField 整形
、models.BigIntegerField 长整形
integer_field_ranges = {
'SmallIntegerField': (-, ),
'IntegerField': (-, ),
'BigIntegerField': (-, ),
'PositiveSmallIntegerField': (, ),
'PositiveIntegerField': (, ),
}
、models.IPAddressField 字符串类型(ip4正则表达式)
、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)
参数protocol可以是:both、ipv4、ipv6
验证时,会根据设置报错
、models.NullBooleanField 允许为空的布尔类型
、models.PositiveIntegerFiel 正Integer
、models.PositiveSmallIntegerField 正smallInteger
、models.SlugField 减号、下划线、字母、数字
、models.SmallIntegerField 数字
数据库中的字段有:tinyint、smallint、int、bigint
、models.TextField 字符串=longtext
、models.TimeField 时间 HH:MM[:ss[.uuuuuu]]
、models.URLField 字符串,地址正则表达式
、models.BinaryField 二进制
、models.ImageField 图片
、models.FilePathField 文件
更多字段
、null=True
数据库中字段是否可以为空
、blank=True
django的 Admin 中添加数据时是否可允许空值
、primary_key = False
主键,对AutoField设置主键后,就会代替原来的自增 id 列
、auto_now 和 auto_now_add
auto_now 自动创建---无论添加或修改,都是当前操作的时间
auto_now_add 自动创建---永远是创建时的时间
、choices
GENDER_CHOICE = (
(u'M', u'Male'),
(u'F', u'Female'),
)
gender = models.CharField(max_length=,choices = GENDER_CHOICE)
、max_length
、default 默认值
、verbose_name Admin中字段的显示名称
、name|db_column 数据库中的字段名称
、unique=True 不允许重复
、db_index = True 数据库索引
、editable=True 在Admin里是否可编辑
、error_messages=None 错误提示
、auto_created=False 自动创建
、help_text 在Admin中提示帮助信息
、validators=[]
、upload-to
更多参数
2、连表结构
一对多:models.ForeignKey(其他表)
多对多:models.ManyToManyField(其他表)
一对一:models.OneToOneField(其他表)
应用场景:
一对多:当一张表中创建一行数据时,有一个单选多下拉框(可以被重复选择)
例如:创建用户信息时候,需要选择一个用户类型[普通用户][金牌用户][铂金用户]等。
多对多:在某表中创建一行数据时,有一个可以多选的下拉框
例如:创建用户信息,需要为用户指定多个爱好
一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框红的内容被用过一次就消失了)
例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表在添加5列数据
二、操作表
1、基本操作
# 增
#
# models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj = models.Tb1(c1='xx', c2='oo')
# obj.save() # 查
#
# models.Tb1.objects.get(id=) # 获取单条数据,不存在则报错(不建议)
# models.Tb1.objects.all() # 获取全部
# models.Tb1.objects.filter(name='seven') # 获取指定条件的数据 # 删
#
# models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 # 改
# models.Tb1.objects.filter(name='seven').update(gender='') # 将指定条件的数据更新,均支持 **kwargs
# obj = models.Tb1.objects.get(id=)
# obj.c1 = ''
# obj.save() # 修改单条数据
基本操作
2、进阶操作(了不起的双下划线)
利用双下划线将字段和对应的操作连接起来
# 获取个数
#
# models.Tb1.objects.filter(name='seven').count() # 大于,小于
#
# models.Tb1.objects.filter(id__gt=) # 获取id大于1的值
# models.Tb1.objects.filter(id__lt=) # 获取id小于10的值
# models.Tb1.objects.filter(id__lt=, id__gt=) # 获取id大于1 且 小于10的值 # in
#
# models.Tb1.objects.filter(id__in=[, , ]) # 获取id等于11、、33的数据
# models.Tb1.objects.exclude(id__in=[, , ]) # not in # contains
#
# models.Tb1.objects.filter(name__contains="ven")
# models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
# models.Tb1.objects.exclude(name__icontains="ven") # range
#
# models.Tb1.objects.filter(id__range=[, ]) # 范围bettwen and # 其他类似
#
# startswith,istartswith, endswith, iendswith, # order by
#
# models.Tb1.objects.filter(name='seven').order_by('id') # asc
# models.Tb1.objects.filter(name='seven').order_by('-id') # desc # limit 、offset
#
# models.Tb1.objects.all()[:] # group by
from django.db.models import Count, Min, Max, Sum
# models.Tb1.objects.filter(c1=).values('id').annotate(c=Count('num'))
# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = GROUP BY "app01_tb1"."id"
进阶操作
3、连接操作(了不起的双下划线)
利用双下划线和_set将表之间的操作连接起来
class UserProfile(models.Model):
user_info = models.OneToOneField('UserInfo')
username = models.CharField(max_length=)
password = models.CharField(max_length=) def __unicode__(self):
return self.username class UserInfo(models.Model):
user_type_choice = (
(, u'普通用户'),
(, u'高级用户'),
)
user_type = models.IntegerField(choices=user_type_choice)
name = models.CharField(max_length=)
email = models.CharField(max_length=)
address = models.CharField(max_length=) def __unicode__(self):
return self.name class UserGroup(models.Model): caption = models.CharField(max_length=) user_info = models.ManyToManyField('UserInfo') def __unicode__(self):
return self.caption class Host(models.Model):
hostname = models.CharField(max_length=)
ip = models.GenericIPAddressField()
user_group = models.ForeignKey('UserGroup') def __unicode__(self):
return self.hostname
表结构实例
user_info_obj = models.UserInfo.objects.filter(id=).first()
print user_info_obj.user_type
print user_info_obj.get_user_type_display()
print user_info_obj.userprofile.password user_info_obj = models.UserInfo.objects.filter(id=).values('email', 'userprofile__username').first()
print user_info_obj.keys()
print user_info_obj.values()
一对一操作
类似一对一
、搜索条件使用 __ 连接
、获取值时使用 . 连接
一对多
user_info_obj = models.UserInfo.objects.get(name=u'武沛齐')
user_info_objs = models.UserInfo.objects.all() group_obj = models.UserGroup.objects.get(caption='CEO')
group_objs = models.UserGroup.objects.all() # 添加数据
#group_obj.user_info.add(user_info_obj)
#group_obj.user_info.add(*user_info_objs) # 删除数据
#group_obj.user_info.remove(user_info_obj)
#group_obj.user_info.remove(*user_info_objs) # 添加数据
#user_info_obj.usergroup_set.add(group_obj)
#user_info_obj.usergroup_set.add(*group_objs) # 删除数据
#user_info_obj.usergroup_set.remove(group_obj)
#user_info_obj.usergroup_set.remove(*group_objs) # 获取数据
#print group_obj.user_info.all()
#print group_obj.user_info.all().filter(id=) # 获取数据
#print user_info_obj.usergroup_set.all()
#print user_info_obj.usergroup_set.all().filter(caption='CEO')
#print user_info_obj.usergroup_set.all().filter(caption='DBA')
多对多操作
# F 使用查询条件的值
#
# from django.db.models import F
# models.Tb1.objects.update(num=F('num')+) # Q 构建搜索条件
from django.db.models import Q
# con = Q()
#
# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', ))
# q1.children.append(('id', ))
# q1.children.append(('id', ))
#
# q2 = Q()
# q2.connector = 'OR'
# q2.children.append(('c1', ))
# q2.children.append(('c1', ))
# q2.children.append(('c1', ))
#
# con.add(q1, 'AND')
# con.add(q2, 'AND')
#
# models.Tb1.objects.filter(con) #
# from django.db import connection
# cursor = connection.cursor()
# cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
# row = cursor.fetchone()
其他操作
注意:xx_set中多[_set]是多对多中多固定搭配
扩展:上传文件实例
class FileForm(forms.Form):
ExcelFile = forms.FileField()
Form
from django.db import models class UploadFile(models.Model):
userid = models.CharField(max_length = )
file = models.FileField(upload_to = './upload/')
date = models.DateTimeField(auto_now_add=True)
Model
def UploadFile(request):
uf = AssetForm.FileForm(request.POST,request.FILES)
if uf.is_valid():
upload = models.UploadFile()
upload.userid =
upload.file = uf.cleaned_data['ExcelFile']
upload.save() print upload.file
View
Form
django中多Form一般有两种功能:
输入html
验证用户输入
#!/usr/bin/env python
# -*- coding:utf- -*-
import re
from django import forms
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 PublishForm(forms.Form): user_type_choice = (
(, u'普通用户'),
(, u'高级用户'),
) user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
attrs={'class': "form-control"})) title = forms.CharField(max_length=,
min_length=,
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=,
widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': })) 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))
View
扩展:ModelForm
在使用Model和Form时,都需要对字段进行定义并制定类型,通过ModelForm则可以省去Form中字段的定义
class AdminModelForm(forms.ModelForm): class Meta:
model = models.Admin
#fields = '__all__'
fields = ('username', 'email') widgets = {
'email' : forms.PasswordInput(attrs={'class':"alex"}),
}
View
跨站请求伪造
一、简介
django为用户实现防止跨站请求伪造的功能,通过中间件django,middleware.csrf.CsrfViewMiddleware来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_project,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:form django.views.decorators.csrf import csrf_exempt,csrf_protect
二、应用
1、普通表单
veiw中设置返回值:
return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
或者
return render(request, 'xxx.html', data) 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
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:request.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失效策略。
更多见:
https://docs.djangoproject.com/en/1.9/topics/http/sessions/
http://docs.30c.org/djangobook2/chapter14/
https://docs.djangoproject.com/en/1.9/ref/settings/#settings-sessions
三、应用
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
分页
一、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] [下一页]
缓存
由于Django时动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者Redis中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存活着Redis中之前缓存的内容拿到,并返回,
一、配置
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(BASE_DIR, 'cache'),
'TIMEOUT': 600,
'OPTIONS': {
'MAX_ENTRIES': 1000
}
}
}
2、应用
from django.shortcuts import render, HttpResponse
from django.views.decorators.cache import cache_page @cache_page(60 * 15)
def func(request):
return HttpResponse('xxx')
更多:
https://docs.djangoproject.com/en/1.9/topics/cache/
http://djangobook.py3k.cn/2.0/chapter15/
Django: 之Model、Cookis、Session的更多相关文章
- django的cookie和session以及内置信号、缓存
cookie和session cookie和session的作用: cookie和session都记录了客户端的某种状态,用来跟踪用户访问网站的整个回话.两者最大的区别是cookie的信息是存放在浏览 ...
- Django(六)Session、CSRF、中间件
大纲 二.session 1.session与cookie对比 2.session基本原理及流程 3.session服务器操作(获取值.设置值.清空值) 4.session通用配置(在配置文件中) 5 ...
- 基于django的自定义简单session功能
基于django的自定义简单session功能 简单思路: 1.建立自定义session数据库 2.登入时将用户名和密码存入session库 3.将自定义的随机session_id写入cookie中 ...
- Django之Cookie、Session、CSRF、Admin
Django之Cookie.Session.CSRF.Admin Cookie 1.获取Cookie: 1 2 3 4 5 6 request.COOKIES['key'] request.get ...
- pyhton框架Django之cookie和session
一,cookie和session的理解 cookies 是浏览器为 Web 服务器存储的一小段信息. 每次浏览器从某个服务器请求页面时,它向服务器回送之前收到的cookies.它保存在浏览器下的某个文 ...
- django的cookie和session以及缓存
cookie和session cookie和session的作用: cookie和session都记录了客户端的某种状态,用来跟踪用户访问网站的整个回话.两者最大的区别是cookie的信息是存放在浏览 ...
- Django之Model操作
Django之Model操作 本节内容 字段 字段参数 元信息 多表关系及参数 ORM操作 1. 字段 字段列表 AutoField(Field) - int自增列,必须填入参数 primary_ke ...
- Django的Model上都有些什么
Django的Model上都有些什么 modelinfo= ['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__' ...
- django的cookie 和session
Cookie 1.获取cookie: request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt=' ...
- Python之路【第二十二篇】:Django之Model操作
Django之Model操作 一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bi ...
随机推荐
- 比较全的 C# 操作 Word的代码
using System;using System.Collections.Generic;using System.Text;using Microsoft.Office.Interop.Word; ...
- li浮动时ul高度为0,解决ul自适应高度的几种方法
网址:http://www.gxchina.com/edu/11208.html 1.给ul元素设置高度height最直接的办法是给ul元素设置一个高度,即ul标签添加height属性,代码如下: u ...
- laravel 邮箱改密功能
参考网址: http://laravelacademy.org/post/1290.html
- JavaScript Function arguments.callee caller length return
一.Function 函数是对象,函数名是指针. 函数名实际上是一个指向函数对象的指针. 使用不带圆括号的函数名是访问函数指针,并非调用函数. 函数的名字仅仅是一个包含指针的变量而已.即使在不同的环境 ...
- weaver_oa
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- 在Java中Arrays工具类实现功能的六种方法
使用Arrays工具类,要先导入包即:import.java.util.Arrays 以下是实现六种功能的方法: 1.比较两个数组值是否相等: 结果为true.false.(布尔型不能比较) int ...
- js第一天 inner html value
<html> <head> <meta charset="utf-8" /> <title></title> <s ...
- .Net日期处理之格式化
一.默认格式 2015/9/3 9:04:31 二.格式2 2015年9月3日 9:28:51 三.格式3 2015年9月3日 9:31 四.格式4 2015/9/3 9:39:01 五.格式5 20 ...
- headless
http://www.oschina.net/translate/using-headless-mode-in-java-se
- sql server两种分页方法
方法一: --分页方法一 OrderID,CustomerID, EmployeeID,OrderDate,ShippedDate,ShipName,ShipAddress,Freight from ...