django 枚举类型的timefield类型怎么显示非整点时间

1973人阅读
Django笔记教程(5)
Model 进阶学习
Django经常被用于一些创业团队,乃是因为其非常适合敏捷开发,开发效率非常之高。Model 作为Django重要组成部分也是亮点之一,着实需要我们花时间好好梳理一遍。
ORM需要好好学习一下,运用得当可以大大的提升代码的简洁性。Django的model模块,遵循了DRY(don’t repeat yourself)原则,也会使得代码更加容易维护,只需修改一次,肯定会大大提高程序的健壮性以及可维护性。
而且ORM也使得该框架更加灵活且松解耦。例如有些码农不喜欢django的模版,更偏爱其他的模版渲染引擎。django视图方法并未强制一定要使用自身的模版引擎,你一可以尝试实用jinjia2等等。同时ORM屏蔽了底层数据库的语法,你可以运行非常多的数据库类型(mysql,mongo?don’t care,改一下engine配置即可),当然性能肯定会降低一些,毕竟多封装了一层。
一路走来,踩过无数的大坑,发现网上很多网友的博文是误导性的,所以想在这里写一片文章梳理一下model的全貌,以备复习,也供给大家一个参考,如果发现错误希望可以帮忙指正,谢谢。
本文结构:
model常用字段定义
model的初级用法
model的高级用法
model的一些坑
1.model常用字段定义
V=models.CharField(max_length=None[, **options])    
V=models.EmailField([max_length=75, **options])    
V=models.URLField([verify_exists=True, max_length=200, **options])    
V=models.FileField(upload_to=None[, max_length=100, **options])    
V=models.ImageField(upload_to=None[, height_field=None, width_field=None, max_length=100, **options])
V=models.IPAddressField([**options])    
V=models.FilePathField(path=None[, match=None, recursive=False, max_length=100, **options]) 
V=models.SlugField([max_length=50, **options])    
maSeparatedIntegerField(max_length=None[, **options])    
V=models.IntegerField([**options])    
V=models.PositiveIntegerField([**options])    
V=models.SmallIntegerField([**options])    
V=models.PositiveSmallIntegerField([**options])    
V=models.AutoField(**options)    
V=models.DecimalField(max_digits=None, decimal_places=None[, **options])    
V=models.FloatField([**options])    
V=models.BooleanField(**options)    
V=models.NullBooleanField([**options])    
V=models.DateField([auto_now=False, auto_now_add=False, **options])    
V=models.DateTimeField([auto_now=False, auto_now_add=False, **options])    
V=models.TimeField([auto_now=False, auto_now_add=False, **options])    
V=models.TextField([**options])    
V=models.XMLField(schema_path=None[, **options])    
——————————————————————————–
V=models.ForeignKey(othermodel[, **options])    
V=models.ManyToManyField(othermodel[, **options])    
V=models.OneToOneField(othermodel[, parent_link=False, **options])    
2.model初级用法
首先我们拿官网的例子作为示范,这个例子非常的经典,被用在django book以及其他很多相关的书籍当中。
我们首先假定如下的概念:
一个作者有姓,名,email地址。
出版商有名称,地址,所在的city,province,country,website.
书籍有书名和出版日期。它有一个或者多个作者[many-2-many]。但是只有一个出版商([one 2 many]),被称为外键[foreign key]。
在models.py中添加如下内容:
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __unicode__(self):
return self.title
并且记得在配置里面加入app model注册,
之后可以用python manage.py validate 校验模型的正确性。
也可以用python mange.py sqlall books 来查看sql生成的语句。
后面还需要执行
python manage.py syncdb
基本的添加数据
基本的选择对象
获取全体对象:
Publisher.objects.all()可以用来获取所有的对象.
筛选部分对象:
Publisher.objects.filter(name='Apress')可以用来筛选所有name是Apress的publisher.(获取的是一个对象列表)
获取单个对象
Publisher.objects.get(name='Apress')
获取一个名字是Apress的开发商(只获取单个对象)。 filter的条件会在高级部分列出。
publisher.objects.order_by("state_province","-address").这句代码几乎囊括了排序的精华:).我们可以看到是多字段排序,同时,address前面有一个-代表的是逆排序。
当然,一般情况下,只需要按照某个字段进行排序,这种情况下可以指定模型的缺省排序方式:
除了单个查询,我们还可以用下面这种方式来查询
Publisher.objects.filter(name='xxoo').order_by('-name')[0]
这段程序并不会执行两次,而是最后转化为一句sql语句来执行(考虑的太周到).
更新多个对象:
我们知道,之前我们用p.save()来更新对象,如果涉及到很多条数据需要一次性更新,这个时候该如何呢?Django也考虑到了这一点,可以用如下的方式来更新:
Publisher.objects.all().update(country='China'),一次性将所有的Publisher的国家更新为china。
前面讲了添加、更新,这里补充一下删除,删除主要是筛选出对象后执行delete()方法.
Publisher.objects.filter(country='USA').delete()
3.model的高级用法
&&&b=Book.objects.get(id=1)
&&&b=p.publisher
&publisher:Apress Publishing&
&&&b.publisher.website
u'http://www.'
对于Foreignkey 来说,关系的另外一端,也可以追溯回来,不过由于不是对称关系,所以有一些区别,获得的是一个list,而非单一对象:
&&&p=Publisher.objects.get(name="Apress Publishing")
&&&p.book_set.all()
[&Book:The Chinese english&,&Book:the good good study&,...]
访问多对多值
多对多和外键工作方式类似,不过我们处理的是QuerySet而非模型实例。例如,查看书籍的作者:
&&&b = Book.objects.get(id=1)
&&&b.authors.all()
[&Author:liushuchun&,&Author:nobb&]
&&&b.authors.filter(fisrt_name="liushuchun")
[&Author:liushuchun&]
我们可以看到这就是类似objects来用了。
更改数据库结构
Django有一个不完善的地方是,一旦model确定下来后,再想通过命令来更新是无法更新的,会报错,这个时候就要学会用手动的方式更改数据库结构。
具体的过程:
1. 先在models.py文件中,找到你要添加字段的模型,添加(也可以是删除修改,只是sql语句有一些区别)上该字段,如下所示(抱歉,截图多了个等号)
在cmd下,通过cd命令进入应用目录,也就是manage.py文件所在的目录
3. 然后使用python manage.py sqlall[app_name]命令,打印出app中包括的所有模型的sql语言表示
3. 找到你想要添加字段的表,找到你已经添加过的字段test,记下sql语句
4. 进入 manage.py shell 创建一个cursor实例,用于执行sql语句
5. 执行该sql语句,看好了,这个sql语句是刚才我让你记下的sql语句,执行这个命令就可以完成向数据库添加字段.
6. 最后,我们要验证添加字段是否成功,仍然在manage.py shell中,通过调用模型来检查是否成功。
这里我们只说了添加字段,其他删除或者修改字段类似。
manager管理器添加自定义方法
管理器是Django查询数据库时会使用到的一个特别的对象,在Book.objects.all()语法中,objects就是管理器,在django中,每一个model至少有一个管理器,而且,你也可以创建自己的管理器来自定义你的数据库访问操作。一方面可以增加额外的管理器方法,另一方面可以根据你的需求来修改管理器返回的QuerySet。
这是一种”表级别”的操作,下面我们给之前的Book类增加一个方法title_count(),它根据关键字,
返回标题中包括这个关键字的书的个数。
class BookManager(models.Manager):
def title_count(self, keyword):
return self.filter(title__icontains=keyword).count()
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
num_pages = models.IntegerField(blank=True, null=True)
objects = BookManager()
def __unicode__(self):
return self.title
&&&Book.objects.title_count('python')
上面的代码可以看到,创建自定义的Manager的步骤:
继承models.Manager,定义新的管理器方法,在方法中使用self,也就是manager本身来
2. 把自定义的管理器对象赋值给objects属性来代替默认的管理器。
那为什么不直接创建个title_count函数来实现这个功能呢?
因为创建管理器类,可以更好地进行封装功能和重用代码。
修改返回的QuerySet
Book.objects.all()返回的是所有记录对象,可以重写Manager.get_query_set()方法,它返回的是你自定义的QuerySet,你之后的filter,slice等操作都是基于这个自定义的QuerySet。
from django.db import models
class RogerBookManager(models.Manager):
def get_query_set(self):
return super(RogerBookManager, self).get_query_set().filter(title__icontains='python')
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
objects = models.Manager()
roger_objects = RogerBookManager()
&&&Book.objects.all()
[&Book:Coplier Theroy&,&Book:python&,...]
&&&Book.roger_objects.all()
[&Book:Python Tutorial&,&Book:Python tools&]
你可以为model定义多个不同的管理器来返回不同的QuerySet,不过要注意一点的是Django
会把你第一个定义的管理器当作是默认的管理器,也就是代码行中最上面定义的管理器。Django
有些其它的功能会使用到默认的管理器,为了能让它正常的工作,一种比较好的做法就是把原始默认
的管理器放在第一个定义。
Model添加方法(这部分是抄书)
和管理器的”表级别”操作相比,model的方法更像是”记录级别”的操作,不过,model的主要设计是用来
用”表级别”操作的,”记录级别”的操作往往是用来表示记录的状态的,是那些没有放在数据库表中,但是也
有意义的数据。举例说明:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if datetime.date(1945, 8, 1) &= self.birth_date &= datetime.date(1964, 12, 31):
return "Baby boomer"
if self.birth_date & datetime.date(1945, 8, 1):
return "Pre-boomer"
return "Post-boomer"
def get_full_name(self):
"Returns the person's full name."
return u'%s %s' % (self.first_name, self.last_name)
运行结果:
&&& p = Person.objects.get(first_name='Barack', last_name='Obama')
&&& p.birth_date
datetime.date(1961, 8, 4)
&&& p.baby_boomer_status()
'Baby boomer'
&&& p.get_full_name()
u'Barack Obama'
执行自定义SQL语句
如果你想执行自定义的SQL语句查询,可以使用django.db.connection对象:
可以使用SQL对数据库中所有的表进行操作,而不用引用特定的model类。
需要注意的是execute()函数使用的SQL语句需要使用到%s这样的格式符,而
不是直接写在里面。
这样的操作比较自由,比较好的做法是把它放在自定义管理器中:
from django.db import connection, models
class PythonBookManager(models.Manager):
def books_titles_after_publication(self, date_string):
cursor = connection.cursor()
cursor.execute("""
SELECT title
FROM books_book
WHERE publication_date & %s""", [date_string])
return [row[0] for row in cursor.fetchall()]
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField(blank=True, null=True)
num_pages = models.IntegerField(blank=True, null=True)
objects = models.Manager()
python_objects = PythonBookManager()
一些django奇技淫巧
还在搜集中,后面会加上.
一些过滤字段方法
1.多表连接查询:当我知道这点的时候顿时觉得django太NX了。
class A(models.Model):
name = models.CharField(u'名称')
class B(models.Model):
aa = models.ForeignKey(A)
B.objects.filter(aa__name__contains='searchtitle')
1.5 我叫它反向查询,后来插入记录1.5,当我知道的时候瞬间就觉得django太太太NX了。
class A(models.Model):
name = models.CharField(u'名称')
class B(models.Model):
aa = models.ForeignKey(A,related_name="FAN")
bb = models.CharField(u'名称')
查A: A.objects.filter(FAN=’XXXX’),都知道related_name的作用,A.FAN.all()是一组以A为外键的B实例,可前面这样的用法是查询出所有(B.aa=A且B.bb=XXXX)的A实例,然后还可以通过__各种关系查找,真赤激!!!
**2.条件选取querySet的时候,filter表示=,exclude表示!=querySet.distinct() 去重复
__exact 精确等于 like 'aaa'
__iexact 精确等于 忽略大小写 ilike 'aaa'
__contains 包含 like '%aaa%'
__icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。
__gte 大于等于
__lte 小于等于
__in 存在于一个list范围内
__startswith 以...开头
__istartswith 以...开头 忽略大小写
__endswith 以...结尾
__iendswith 以...结尾,忽略大小写
__range 在...范围内
__year 日期字段的年份
__month 日期字段的月份
__day 日期字段的日
__isnull=True/False
&& q1 = Entry.objects.filter(headline__startswith="What")
&& q2 = q1.exclude(pub_date__gte=datetime.date.today())
&& q3 = q1.filter(pub_date__gte=datetime.date.today())
&&& q = q.filter(pub_date__lte=datetime.date.today())
&&& q = q.exclude(body_text__icontains="food")
即q1.filter(pub_date__gte=datetime.date.today())表示为时间&=now,q1.exclude(pub_date__gte=datetime.date.today())表示为&=now
关于缓存:
queryset是有缓存的,a = A.objects.all(),print [i for i in a].第一次执行打印会查询数据库,然后结果会被保存在queryset内置的cache中,再执行print的时候就会取自缓存。
DJANGO or 查询
Q查询——对对象的复杂查询
F查询——专门取对象中某列值的操作
1、Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询,例如:
from django.db.models import Q
from login.models import New
news=New.objects.filter(Q(question__startswith='What'))
2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
Q(question__startswith='Who') | Q(question__startswith='What')
3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
4、应用范围
Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '' OR pub_date = '')
5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
Done!有一些粗略,但是大概能用的上的,几乎都在这里了。
the dango book2.0
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:454229次
积分:3798
积分:3798
排名:第7572名
原创:60篇
转载:22篇
评论:72条
(3)(10)(2)(4)(4)(1)(1)(1)(3)(1)(2)(6)(1)(3)(7)(3)(3)(5)(11)(3)(6)(1)(8)django进阶 - 推酷
django进阶
到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:
创建数据库,设计表结构和字段
使用 MySQLdb 来连接数据库,并编写数据访问层代码
业务逻辑层去调用数据访问层执行数据库操作
import MySQLdb
def GetList(sql):
db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost')
cursor = db.cursor()
cursor.execute(sql)
data = cursor.fetchall()
db.close()
return data
def GetSingle(sql):
db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', 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 的原则,即:根据代码中定义的类来自动生成数据库表。
from django.db import models
class userinfo(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField()
memo = models.TextField()
AutoField(Field)
- int自增列,必须填入参数 primary_key=True
BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True
注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models
class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32)
class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) - ~
PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~
BigIntegerField(IntegerField):
- 长整型(有符号的) -4775808 ~ 4775807
自定义无符号整数字段
class UnsignedIntegerField(models.IntegerField):
def db_type(self, connection):
return 'integer UNSIGNED'
PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',
BooleanField(Field)
- 布尔值类型
NullBooleanField(Field):
- 可以为空的布尔值
CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度
TextField(Field)
- 文本类型
EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制
IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL
SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字
UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
文件夹路径
match=None,
recursive=False,
递归下面的文件夹
allow_files=True,
allow_folders=False,
允许文件夹
FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
upload_to = ""
上传文件的保存路径
storage = None
存储组件,默认django.core.files.storage.FileSystemStorage
ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
upload_to = ""
上传文件的保存路径
storage = None
存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None,
上传图片的高度保存的数据库字段名(字符串)
height_field=None
上传图片的宽度保存的数据库字段名(字符串)
DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
DateField(DateTimeCheckMixin, Field)
- 日期格式
YYYY-MM-DD
TimeField(DateTimeCheckMixin, Field)
- 时间格式
HH:MM[:ss[.uuuuuu]]
DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
FloatField(Field)
DecimalField(Field)
- 10进制小数
max_digits,小数总长度
decimal_places,小数位长度
BinaryField(Field)
- 二进制类型
数据库中字段是否可以为空
数据库中字段的列名
db_tablespace
数据库中字段的默认值
primary_key
数据库中字段是否为主键
数据库中字段是否可以建立索引
数据库中字段是否可以建立唯一索引
unique_for_date
数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month
数据库中字段【月】部分是否可以建立唯一索引
unique_for_year
数据库中字段【年】部分是否可以建立唯一索引
verbose_name
Admin中显示的字段名称
Admin中是否允许用户输入为空
Admin中是否可以编辑
Admin中该字段的提示信息
Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
error_messages
自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'}
validators
自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)
class Meta:
# 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
db_table = "table_name"
# 联合索引
index_together = [
("pub_date", "deadline"),
# 联合唯一索引
unique_together = (("driver", "restaurant"),)
# admin中显示的表名称
verbose_name
# verbose_name加s
verbose_name_plural
更多:/en/1.10/ref/models/options/
1.触发Model中的验证和错误提示有两种方式:
a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息
b. 调用Model对象的 clean_fields 方法,如:
# models.py
class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)
email = models.EmailField(error_messages={'invalid': '格式错了.'})
# views.py
def index(request):
obj = models.UserInfo(username='11234', email='uu')
print(obj.clean_fields())
except Exception as e:
return HttpResponse('ok')
# Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。
2.Admin中修改错误提示
# admin.py
from django.contrib import admin
from model_club import models
from django import forms
class UserInfoForm(forms.ModelForm):
username = forms.CharField(error_messages={'required': '用户名不能为空.'})
email = forms.EmailField(error_messages={'invalid': '邮箱格式错误.'})
age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'})
class Meta:
model = models.UserInfo
# fields = ('username',)
fields = "__all__"
class UserInfoAdmin(admin.ModelAdmin):
form = UserInfoForm
admin.site.register(models.UserInfo, UserInfoAdmin)连表结构
一对多:models.ForeignKey(其他表)
多对多:models.ManyToManyField(其他表)
一对一:models.OneToOneField(其他表)
ForeignKey(ForeignObject) # ForeignObject(RelatedField)
# 要进行关联的表名
to_field=None,
# 要关联的表中的字段名称
on_delete=None,
# 当删除关联表中的数据时,当前表与其关联的行的行为
- models.CASCADE,删除关联数据,与之关联也删除
- models.DO_NOTHING,删除关联数据,引发错误IntegrityError
- models.PROTECT,删除关联数据,引发错误ProtectedError
- models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
- models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
- models.SET,删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
def func():
class MyModel(models.Model):
user = models.ForeignKey(
to="User",
to_field="id"
on_delete=models.SET(func),)
related_name=None,
# 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
related_query_name=None,
# 反向操作时,使用的连接前缀,用于替换【表名】
如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
limit_choices_to=None,
# 在Admin或ModelForm中显示关联数据时,提供的条件:
- limit_choices_to={'nid__gt': 5}
- limit_choices_to=lambda : {'nid__gt': 5}
from django.db.models import Q
- limit_choices_to=Q(nid__gt=10)
- limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
db_constraint=True
# 是否在数据库中创建外键约束
parent_link=False
# 在Admin中是否显示关联数据
OneToOneField(ForeignKey)
# 要进行关联的表名
to_field=None
# 要关联的表中的字段名称
on_delete=None,
# 当删除关联表中的数据时,当前表与其关联的行的行为
###### 对于一对一 ######
# 1. 一对一其实就是 一对多 + 唯一索引
# 2.当两个类之间有继承关系时,默认会创建一个一对一字段
# 如下会在A表中额外增加一个c_ptr_id列且唯一:
class C(models.Model):
nid = models.AutoField(primary_key=True)
part = models.CharField(max_length=12)
class A(C):
id = models.AutoField(primary_key=True)
code = models.CharField(max_length=1)
ManyToManyField(RelatedField)
# 要进行关联的表名
related_name=None,
# 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
related_query_name=None,
# 反向操作时,使用的连接前缀,用于替换【表名】
如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
limit_choices_to=None,
# 在Admin或ModelForm中显示关联数据时,提供的条件:
- limit_choices_to={'nid__gt': 5}
- limit_choices_to=lambda : {'nid__gt': 5}
from django.db.models import Q
- limit_choices_to=Q(nid__gt=10)
- limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
symmetrical=None,
# 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
# 做如下操作时,不同的symmetrical会有不同的可选字段
models.BB.objects.filter(...)
# 可选字段有:code, id, m1
class BB(models.Model):
code = models.CharField(max_length=12)
m1 = models.ManyToManyField('self',symmetrical=True)
# 可选字段有: bb, code, id, m1
class BB(models.Model):
code = models.CharField(max_length=12)
m1 = models.ManyToManyField('self',symmetrical=False)
through=None,
# 自定义第三张表时,使用字段用于指定关系表
through_fields=None,
# 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=50)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
through='Membership',
through_fields=('group', 'person'),
class Membership(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
inviter = models.ForeignKey(
on_delete=models.CASCADE,
related_name="membership_invites",
invite_reason = models.CharField(max_length=64)
db_constraint=True,
# 是否在数据库中创建外键约束
db_table=None,
# 默认创建第三张表时,数据库中表的名称
字段和参数
# models.Tb1.objects.create(c1='xx', c2='oo')
增加一条数据,可以接受字典类型数据 **kwargs
# obj = models.Tb1(c1='xx', c2='oo')
# obj.save()
# models.Tb1.objects.get(id=123)
# 获取单条数据,不存在则报错(不建议)
# 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='0')
# 将指定条件的数据更新,均支持 **kwargs
# obj = models.Tb1.objects.get(id=1)
# obj.c1 = '111'
# obj.save()
# 修改单条数据
进阶操作(了不起的双下划线)
利用双下划线将字段和对应的操作连接起来
1 # 获取个数
# models.Tb1.objects.filter(name='seven').count()
# 大于,小于
# models.Tb1.objects.filter(id__gt=1)
# 获取id大于1的值
# models.Tb1.objects.filter(id__gte=1)
# 获取id大于等于1的值
# models.Tb1.objects.filter(id__lt=10)
# 获取id小于10的值
# models.Tb1.objects.filter(id__lte=10)
# 获取id小于10的值
# models.Tb1.objects.filter(id__lt=10, id__gt=1)
# 获取id大于1 且 小于10的值
# models.Tb1.objects.filter(id__in=[11, 22, 33])
# 获取id等于11、22、33的数据
# models.Tb1.objects.exclude(id__in=[11, 22, 33])
# Entry.objects.filter(pub_date__isnull=True)
# contains
# models.Tb1.objects.filter(name__contains="ven")
# models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
# models.Tb1.objects.exclude(name__icontains="ven")
# models.Tb1.objects.filter(id__range=[1, 2])
# 范围bettwen and
# 其他类似
# startswith,istartswith, endswith, iendswith,
# order by
# models.Tb1.objects.filter(name='seven').order_by('id')
# models.Tb1.objects.filter(name='seven').order_by('-id')
# group by
# from django.db.models import Count, Min, Max, Sum
# models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
# limit 、offset
# models.Tb1.objects.all()[10:20]
# regex正则匹配,iregex 不区分大小写
# Entry.objects.get(title__regex=r'^(An?|The) +')
# Entry.objects.get(title__iregex=r'^(an?|the) +')
# Entry.objects.filter(pub_date__date=datetime.date())
# Entry.objects.filter(pub_date__date__gt=datetime.date())
# Entry.objects.filter(pub_date__year=2005)
# Entry.objects.filter(pub_date__year__gte=2005)
# Entry.objects.filter(pub_date__month=12)
# Entry.objects.filter(pub_date__month__gte=6)
# Entry.objects.filter(pub_date__day=3)
# Entry.objects.filter(pub_date__day__gte=3)
# week_day
# Entry.objects.filter(pub_date__week_day=2)
# Entry.objects.filter(pub_date__week_day__gte=2)
# Event.objects.filter(timestamp__hour=23)
# Event.objects.filter(time__hour=5)
# Event.objects.filter(timestamp__hour__gte=12)
# Event.objects.filter(timestamp__minute=29)
# Event.objects.filter(time__minute=46)
# Event.objects.filter(timestamp__minute__gte=29)
# Event.objects.filter(timestamp__second=31)
# Event.objects.filter(time__second=2)
# Event.objects.filter(timestamp__second__gte=31)
# extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
Entry.objects.extra(select={'new_id': "select col from sometable where othercol & %s"}, select_params=(1,))
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
Entry.objects.extra(select={'new_id': "select id from tb where id & %s"}, select_params=(1,), order_by=['-nid'])
# from django.db.models import F
# models.Tb1.objects.update(num=F('num')+1)
# 方式一:
# Q(nid__gt=10)
# Q(nid=8) | Q(nid__gt=10)
# Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
# 方式二:
# con = Q()
# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', 1))
# q1.children.append(('id', 10))
# q1.children.append(('id', 9))
# q2 = Q()
# q2.connector = 'OR'
# q2.children.append(('c1', 1))
# q2.children.append(('c1', 10))
# q2.children.append(('c1', 9))
# con.add(q1, 'AND')
# con.add(q2, 'AND')
# models.Tb1.objects.filter(con)
# 执行原生SQL
# from django.db import connection, connections
# cursor = connection.cursor()
# cursor = connections['default'].cursor()
# cursor.execute("""SELECT * from auth_user where id = %s""", [1])
# row = cursor.fetchone()
连表操作(了不起的双下划线)
利用双下划线和 _set 将表之间的操作连接起来
1 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.username
10 class 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.name
24 class UserGroup(models.Model):
caption = models.CharField(max_length=64)
user_info = models.ManyToManyField('UserInfo')
def __unicode__(self):
return self.caption
34 class Host(models.Model):
hostname = models.CharField(max_length=64)
ip = models.GenericIPAddressField()
user_group = models.ForeignKey('UserGroup')
def __unicode__(self):
return self.hostname
表结构实例
1 user_info_obj = models.UserInfo.objects.filter(id=1).first()
2 print user_info_obj.user_type
3 print user_info_obj.get_user_type_display()
4 print user_info_obj.userprofile.password
6 user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first()
7 print user_info_obj.keys()
8 print user_info_obj.values()
1 类似一对一
2 1、搜索条件使用 __ 连接
3 2、获取值时使用 .
1 user_info_obj = models.UserInfo.objects.get(name=u'武沛齐')
2 user_info_objs = models.UserInfo.objects.all()
4 group_obj = models.UserGroup.objects.get(caption='CEO')
5 group_objs = models.UserGroup.objects.all()
7 # 添加数据
8 #group_obj.user_info.add(user_info_obj)
9 #group_obj.user_info.add(*user_info_objs)
11 # 删除数据
12 #group_obj.user_info.remove(user_info_obj)
13 #group_obj.user_info.remove(*user_info_objs)
15 # 添加数据
16 #user_info_obj.usergroup_set.add(group_obj)
17 #user_info_obj.usergroup_set.add(*group_objs)
19 # 删除数据
20 #user_info_obj.usergroup_set.remove(group_obj)
21 #user_info_obj.usergroup_set.remove(*group_objs)
23 # 获取数据
24 #print group_obj.user_info.all()
25 #print group_obj.user_info.all().filter(id=1)
27 # 获取数据
28 #print user_info_obj.usergroup_set.all()
29 #print user_info_obj.usergroup_set.all().filter(caption='CEO')
30 #print user_info_obj.usergroup_set.all().filter(caption='DBA')
a、自定义上传
1 def upload_file(request):
if request.method == "POST":
obj = request.FILES.get('fafafa')
f = open(obj.name, 'wb')
for chunk in obj.chunks():
f.write(chunk)
return render(request, 'file.html')
b、Form上传文件实例
1 class FileForm(forms.Form):
ExcelFile = forms.FileField()
1 from django.db import models
3 class UploadFile(models.Model):
userid = models.CharField(max_length = 30)
file = models.FileField(upload_to = './upload/')
date = models.DateTimeField(auto_now_add=True)
1 def UploadFile(request):
uf = AssetForm.FileForm(request.POST,request.FILES)
if uf.is_valid():
upload = models.UploadFile()
upload.userid = 1
upload.file = uf.cleaned_data['ExcelFile']
upload.save()
print upload.file
二、跨站请求伪造
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中设置返回值:
2   return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
return render(request, 'xxx.html', data)
6 html中设置Token:
7   {% csrf_token %}
对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。
1 from django.template.context import RequestContext
2 # Create your views here.
5 def test(request):
if request.method == 'POST':
print request.POST
return HttpResponse('ok')
render_to_response('app01/test.html',context_instance=RequestContext(request))
1 &!DOCTYPE html&
3 &head lang="en"&
&meta charset="UTF-8"&
&title&&/title&
{% 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(){
url:"/app01/test/",
data:{id:1},
type:'POST',
success:function(data){
console.log(data);
41 &/body&
42 &/html&
三、cookie
1、获取cookie
request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
default: 默认值
salt: 加密盐
max_age: 后台控制过期时间
2、设置cookie
rep = HttpResponse(...) 或 rep = render(request, ...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
max_age=None,
expires=None,
超时时间(IE requires expires, so set it if hasn't been already.)
Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
domain=None,
Cookie生效的域名
secure=False,
httponly=False
只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。
&script src='/static/js/jquery.cookie.js'&&/script&
$.cookie("list_pager_num", 30,{ path: '/' });
四、session
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
数据库(默认)
缓存+数据库
加密cookie
1、数据库Session
1 Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
3 a. 配置 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,默认修改之后才保存(默认)
18 b. 使用
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")
2、缓存session
1 a. 配置 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,默认修改之后才保存
18 b. 使用
3、文件session
1 a. 配置 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,默认修改之后才保存
16 b. 使用
4、缓存+数据库session
1 数据库用于做持久化,缓存用于提高效率
3 a. 配置 settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
5、加密cookie session
1 a. 配置 settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
更多参考:
扩展:Session用户验证
1 def login(func):
def wrap(request, *args, **kwargs):
# 如果未登陆,跳转到指定页面
if request.path == '/test/':
return redirect('')
return func(request, *args, **kwargs)
return wrap
1、Django内置分页
2、自定义分页
分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。
a、设定每页显示数据条数
b、用户输入页码(第一页、第二页...)
c、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
d、在数据表中根据起始位置取值,页面上输出数据
需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]
1、设定每页显示数据条数
2、用户输入页码(第一页、第二页...)
3、设定显示多少页号
4、获取当前数据总条数
5、根据设定显示多少页号和数据总条数计算出,总页数
6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
7、在数据表中根据起始位置取值,页面上输出数据
8、输出分页html,如:[上一页][1][2][3][4][5][下一页]
1 #!/usr/bin/env python
2 # _*_coding:utf-8_*_
3 from django.utils.safestring import mark_safe
5 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]
return result[0]+1
21 def Custompager(baseurl,currentPage,totalpage):
#基础页,当前页,总页数
perPager=11
#总页数&11
#0 -- totalpage
#总页数&11
#当前页大于5 currentPage-5 -- currentPage+5
#currentPage+5是否超过总页数,超过总页数,end就是总页数
#当前页小于5 0 -- 11
if totalpage &= 11:
end=totalpage
if currentPage&5:
begin=currentPage-5
end=currentPage+5
if end & totalpage:
end=totalpage
pager_list=[]
if currentPage&=1:
first="&a href=''&首页&/a&"
first="&a href='%s%d'&首页&/a&" % (baseurl,1)
pager_list.append(first)
if currentPage&=1:
prev="&a href=''&上一页&/a&"
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)
temp="&a href='%s%d'&%d&/a&" % (baseurl,i,i)
pager_list.append(temp)
if currentPage&=totalpage:
next="&a href='#'&下一页&/a&"
next="&a href='%s%d'&下一页&/a&" % (baseurl,currentPage+1)
pager_list.append(next)
if currentPage&=totalpage:
last="&a href=''&末页&/a&"
last="&a href='%s%d'&末页&/a&" % (baseurl,totalpage)
pager_list.append(last)
result=''.join(pager_list)
return mark_safe(result)
#把字符串转成html语言
由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。
Django中提供了6种缓存方式:
Memcache缓存(python-memcached模块)
Memcache缓存(pylibmc模块)
a、开发调试
# 此为开始调试用,实际内部不做任何操作
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
'TIMEOUT': 300,
# 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
'OPTIONS':{
'MAX_ENTRIES': 300,
# 最大缓存个数(默认300)
'CULL_FREQUENCY': 3,
# 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
'KEY_PREFIX': '',
# 缓存key的前缀(默认空)
'VERSION': 1,
# 缓存key的版本(默认1)
'KEY_FUNCTION' 函数名
# 生成key的函数(默认函数会生成为:【前缀:版本:key】)
# 自定义key
def default_key_func(key, key_prefix, version):
Default function to generate keys.
Constructs the key used by all other methods. By default it prepends
the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
function with custom key making behavior.
return '%s:%s:%s' % (key_prefix, version, key)
def get_key_func(key_func):
Function to decide which key function to use.
Defaults to ``default_key_func``.
if key_func is not None:
if callable(key_func):
return key_func
return import_string(key_func)
return default_key_func
# 此缓存将内容保存至内存的变量中
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
# 注:其他配置同开发调试版本
1 # 此缓存将内容保存至文件
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
# 注:其他配置同开发调试版本
# 此缓存将内容保存至数据库
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table', # 数据库表
# 注:执行创建表命令 python manage.py createcachetable
e、Memcache缓存(python-memcached模块)
1 # 此缓存使用python-memcached模块连接memcache
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
f、Memcache缓存(pylibmc模块)
a. 全站使用
# 此缓存使用pylibmc模块连接memcache
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '/tmp/memcached.sock',
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
b.&单独视图缓存
c、局部视图使用
七、序列化
关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。
1、serializers
from django.core import serializers
ret = models.BookType.objects.all()
data = serializers.serialize("json", ret)
2、json.dumps
import json
#ret = models.BookType.objects.all().values('caption')
ret = models.BookType.objects.all().values_list('caption')
ret=list(ret)
result = json.dumps(ret)
由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:
import json
from datetime import date
from datetime import datetime
class JsonCustomEncoder(json.JSONEncoder):
def default(self, field):
if isinstance(field, datetime):
return o.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(field, date):
return o.strftime('%Y-%m-%d')
return json.JSONEncoder.default(self, field)
# ds = json.dumps(d, cls=JsonCustomEncoder)
Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。
1、Django内置信号
Model signals
# django的modal执行其构造方法前,自动触发
# django的modal执行其构造方法后,自动触发
# django的modal对象保存前,自动触发
# django的modal对象保存后,自动触发
pre_delete
# django的modal对象删除前,自动触发
post_delete
# django的modal对象删除后,自动触发
m2m_changed
# django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
class_prepared
# 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
pre_migrate
# 执行migrate命令前,自动触发
post_migrate
# 执行migrate命令后,自动触发
Request/response signals
request_started
# 请求到来前,自动触发
request_finished
# 请求结束后,自动触发
got_request_exception
# 请求异常后,自动触发
Test signals
setting_changed
# 使用test测试修改配置文件时,自动触发
template_rendered
# 使用test测试渲染模板时,自动触发
Database Wrappers
connection_created
# 创建数据库连接时,自动触发
2、自定义信号
a. 定义信号
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
b. 注册信号
def callback(sender, **kwargs):
print("callback")
print(sender,kwargs)
pizza_done.connect(callback)
from 路径 import pizza_done
pizza_done.send(sender='seven',toppings=123, size=456)
由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 django model类型 的文章

 

随机推荐