字段 | DB Type |
---|---|
AutoField | integer AUTO_INCREMENT |
BigAutoField | bigint AUTO_INCREMENT |
BinaryField | longblob |
BooleanField | bool |
CharField | varchar |
CommaSeparatedIntegerField | varchar |
DateField | date |
DateTimeField | datetime |
DecimalField | numeric |
DurationField | bigint |
FileField | varchar |
FilePathField | varchar |
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 |
SmallIntegerField | smallint |
TextField | longtext |
TimeField | time |
UUIDField | char(32) |
字段 | 说明 |
---|---|
AutoField | int自增列,必须填入参数 primary_key=True。当model中若是没有自增列,则自动会建立一个列名为id的列。 |
IntegerField | 一个整数类型,范围在 -2147483648 to 2147483647。 |
CharField | 字符类型,必须提供max_length参数, max_length表示字符长度。 |
DateField | 日期字段,日期格式 YYYY-MM-DD,至关于Python中的datetime.date()实例。 |
DateTimeField | 日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至关于Python中的datetime.datetime()实例。 |
BigAutoField | bigint自增列,必须填入参数 primary_key=True。当model中若是没有自增列,则自动会建立一个列名为id的列。 |
SmallIntegerField | 小整数 -32768 ~ 32767 |
PositiveSmallIntegerField | 正小整数 0 ~ 32767 |
PositiveIntegerField | 正整数 0 ~ 2147483647 |
BigIntegerField | 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 |
BooleanField | 布尔值类型 |
NullBooleanField | 能够为空的布尔值 |
TextField | 文本类型 |
EmailField | 字符串类型,Django Admin以及ModelForm中提供验证机制 |
IPAddressField | 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 |
GenericIPAddressField | 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 |
URLField | 字符串类型,Django Admin以及ModelForm中提供验证 URL |
SlugField | 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、链接符(减号) |
CommaSeparatedIntegerField | 字符串类型,格式必须为逗号分割的数字 |
UUIDField | 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 |
FilePathField | 字符串,路径保存在数据库,文件上传到指定目录 |
ImageField | 字符串,路径保存在数据库,文件上传到指定目录 |
TimeField | 时间格式 HH:MM[:ss[.uuuuuu]] |
DurationField | 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 |
FloatField | 浮点型 |
DecimalField | 10进制小数 |
BinaryField | 二进制类型 |
此处示例为建立一个对应db中char类型的字段git
1 class FixedCharField(models.Field): 2 """ 3 自定义的char类型的字段类 4 """ 5 def __init__(self, max_length, *args, **kwargs): 6 self.max_length = max_length 7 super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs) 8 9 def db_type(self, connection): 10 """ 11 限定生成数据库表的字段类型为char,长度为max_length指定的值 12 """ 13 return 'char(%s)' % self.max_length
1 class Class(models.Model): 2 id = models.AutoField(primary_key=True) 3 # 使用自定义的char类型的字段 4 name= FixedCharField(max_length=25)
参数 | 说明 | 可用字段 |
---|---|---|
null | 用于表示某个字段能够为空。 | all |
unique | 若是设置为unique=True 则该字段在此表中必须是惟一的 。 | all |
db_index | 若是db_index=True 则表明着为此字段设置索引。 | all |
default | 为该字段设置默认值。 | all |
auto_now_add | 配置auto_now_add=True,建立数据记录的时候会把当前时间添加到数据库 | DateField和DateTimeField |
auto_now | 配置上auto_now=True,每次更新数据记录的时候会更新该字段。 | DateField和DateTimeField |
外键类型在ORM中用来表示外键关联关系,通常把ForeignKey字段设置在 '一对多'中'多'的一方。ForeignKey能够和其余表作关联关系同时也能够和自身作关联关系。spring
设置要关联的表sql
设置要关联的表的字段数据库
反向操做时,使用的字段名,用于代替原反向查询时的'表名_set'。django
1 # 班级 2 class Classes(models.Model): 3 name = models.CharField(max_length=32) 4 # 学生 5 class Student(models.Model): 6 name = models.CharField(max_length=32) 7 theclass = models.ForeignKey(to="Classes") 8 9 # 当咱们要查询某个班级关联的全部学生(反向查询)时,咱们会这么写: 10 models.Classes.objects.first().student_set.all() 11 12 # 当咱们在ForeignKey字段中添加了参数related_name后: 13 class Student(models.Model): 14 name = models.CharField(max_length=32) 15 theclass = models.ForeignKey(to="Classes", related_name="students") 16 17 # 当咱们要查询某个班级关联的全部学生(反向查询)时,咱们会这么写: 18 models.Classes.objects.first().students.all()
反向查询操做时,使用的链接前缀,用于替换表名。api
当删除关联表中的数据时,当前表与其关联的行的行为。数据结构
值 | 说明 |
---|---|
models.CASCADE | 删除关联数据,与之关联也删除 |
models.DO_NOTHING | 删除关联数据,引起错误IntegrityError |
models.PROTECT | 删除关联数据,引起错误ProtectedError |
models.SET_NULL | 删除关联数据,与之关联的值设置为null(前提FK字段须要设置为可空) |
models.SET_DEFAULT | 删除关联数据,与之关联的值设置为默认值(前提FK字段须要设置默认值) |
models.SET | 删除关联数据,app a. 与之关联的值设置为指定值,设置:models.SET(值)。ide b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)。函数 ![]() 1 def func(): 2 return 10 3 4 5 class MyModel(models.Model): 6 user = models.ForeignKey( 7 to="User", 8 to_field="id", 9 on_delete = models.SET(func) 10 ) |
是否在数据库中建立外键约束,默认为True。
一对一字段。一般用来扩展已有字段。
一对一的关联关系多用在当一张表的不一样字段查询频次差距过大的状况下,将本能够存储在一张表的字段拆开放置在两张表中,而后将两张表创建一对一的关联关系。
1 class Author(models.Model): 2 name = models.CharField(max_length=32) 3 info = models.OneToOneField(to='AuthorInfo') 4 5 6 class AuthorInfo(models.Model): 7 phone = models.CharField(max_length=11) 8 email = models.EmailField()
设置要关联的表。
设置要关联的字段。
同ForeignKey字段。
用于表示多对多的关联关系。在数据库中经过第三张表来创建关联关系。
设置要关联的表。
同ForeignKey字段。
同ForeignKey字段。
仅用于多对多自关联时,指定内部是否不建立反向操做的属性(表名_set)。默认为True(不建立)。
1 class Person(models.Model): 2 name = models.CharField(max_length=16) 3 friends = models.ManyToManyField("self") 4 # 此时,person对象就没有person_set属性。 5 6 class Person(models.Model): 7 name = models.CharField(max_length=16) 8 friends = models.ManyToManyField("self", symmetrical=False) 9 # 此时,person对象如今就可使用person_set属性进行反向查询。
在使用ManyToManyField字段时,Django将自动生成一张表来管理多对多的关联关系。但咱们也能够手动建立第三张表来管理多对多关系,此时就须要经过through来指定第三张表的表名。
设置关联的字段。
默认建立第三张表时,数据库中表的名称。
1 class Book(models.Model): 2 title = models.CharField(max_length=32, verbose_name="书名") 3 4 5 class Author(models.Model): 6 name = models.CharField(max_length=32, verbose_name="做者姓名") 7 8 9 # 本身建立第三张表,分别经过外键关联书和做者 10 class Author2Book(models.Model): 11 author = models.ForeignKey(to="Author") 12 book = models.ForeignKey(to="Book") 13 14 class Meta: 15 unique_together = ("author", "book")
1 class Book(models.Model): 2 title = models.CharField(max_length=32, verbose_name="书名") 3 4 5 # 经过ORM自带的ManyToManyField自动建立第三张表 6 class Author(models.Model): 7 name = models.CharField(max_length=32, verbose_name="做者姓名") 8 books = models.ManyToManyField(to="Book", related_name="authors")
1 class Book(models.Model): 2 title = models.CharField(max_length=32, verbose_name="书名") 3 4 5 # 本身建立第三张表,并经过ManyToManyField指定关联 6 class Author(models.Model): 7 name = models.CharField(max_length=32, verbose_name="做者姓名") 8 books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book")) 9 # through_fields接受一个2元组('field1','field2'): 10 # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。 11 12 13 class Author2Book(models.Model): 14 author = models.ForeignKey(to="Author") 15 book = models.ForeignKey(to="Book") 16 17 class Meta: 18 unique_together = ("author", "book")
注意: 当咱们须要在第三张关系表中存储额外的字段时,就要使用第三种方式。 可是当咱们使用第三种方式建立多对多关联关系时,就没法使用set、add、remove、clear方法来管理多对多的关系了,须要经过第三张表的model来管理多对多关系。
ORM对应的类里面包含另外一个Meta类,而Meta类封装了一些数据库的信息。主要字段以下:
ORM在数据库中的表名默认是 app_类名,能够经过db_table能够重写表名。
联合索引。
联合惟一索引。
指定默认按什么字段排序。 只有设置了该属性,咱们查询到的结果才能够被reverse()。
函数 | 说明 | 返回值 |
---|---|---|
all() | 查询全部结果。 | QuerySet |
filter(**kwargs) | 它包含了与所给筛选条件相匹配的对象。 | QuerySet |
get(**kwargs) | 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,若是符合筛选条件的对象超过一个或者没有都会抛出错误。 | 单个对象 |
exclude(**kwargs) | 它包含了与所给筛选条件不匹配的对象。 | QuerySet |
values(*field) | 返回一个ValueQuerySet——一个特殊的QuerySet,运行后获得的并非一系列model的实例化对象,而是一个可迭代的字典序列。 | 特殊的QuerySet |
values_list(*field) | 它与values()很是类似,它返回的是一个元组序列,values返回的是一个字典序列。 | 特殊的QuerySet |
order_by(*field) | 对查询结果排序。 | QuerySet |
reverse() | 对查询结果反向排序,请注意reverse()一般只能在具备已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。 | QuerySet |
distinct() | 从返回结果中剔除重复纪录(若是你查询跨越多个表,可能在计算QuerySet时获得重复的结果。此时可使用distinct(),注意只有在PostgreSQL中支持按字段去重。) | QuerySet |
count() | 返回数据库中匹配查询(QuerySet)的对象数量。 | integer |
first() | 返回第一条记录。 | 单个对象 |
last() | 返回最后一条记录。 | 单个对象 |
exists() | 若是QuerySet包含数据,就返回True,不然返回False | boolean |
1 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 2 3 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于十一、2二、33的数据 4 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 5 6 models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的 7 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 8 9 models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and 10 11 相似的还有:startswith,istartswith, endswith, iendswith 12 13 date字段还能够: 14 models.Class.objects.filter(first_day__year=2017)
1 book_obj = models.Book.objects.first() # 第一本书对象 2 print(book_obj.publisher) # 获得这本书关联的出版社对象 3 print(book_obj.publisher.name) # 获得出版社对象的名称
1 print(models.Book.objects.values_list("publisher__name"))
1 publisher_obj = models.Publisher.objects.first() # 找到第一个出版社对象 2 books = publisher_obj.book_set.all() # 找到第一个出版社出版的全部书 3 titles = books.values_list("title") # 找到第一个出版社出版的全部书的书名
1 titles = models.Publisher.objects.values_list("book__title")
"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。
它存在于下面两种状况:
外键关系的反向查询
多对多关联关系
简单来讲就是当点(".")后面的对象可能存在多个的时候就可使用如下的方法。
建立一个新的对象,保存对象,并将它添加到关联对象集之中,返回新建立的对象。
1 import datetime 2 models.Author.objects.first().book_set.create(title="番茄物语", publish_date=datetime.date.today())
添加对象,把指定的model对象添加到关联对象集中。
1 author_objs = models.Author.objects.filter(id__lt=3) 2 models.Book.objects.first().authors.add(*author_objs) 3 # 直接用id关联 4 models.Book.objects.first().authors.add(*[1, 2])
更新model对象的关联对象。
1 book_obj = models.Book.objects.first() 2 book_obj.authors.set([2, 3])
从关联对象集中移除执行的model对象。
1 book_obj = models.Book.objects.first() 2 book_obj.authors.remove(3)
从关联对象集中移除一切对象。
1 book_obj = models.Book.objects.first() 2 book_obj.authors.clear()
现有模型及其数据信息以下:
1 from django.db import models 2 3 4 class Press(models.Model): 5 ''' 6 出版社 7 ''' 8 id = models.AutoField(primary_key=True) 9 name = models.CharField(max_length=50, unique=True) 10 11 12 class Book(models.Model): 13 ''' 14 书籍 15 ''' 16 id = models.AutoField(primary_key=True) 17 name = models.CharField(max_length=50, unique=True) 18 price = models.DecimalField(max_digits=5, decimal_places=2) 19 stock = models.IntegerField() 20 saleNumber = models.IntegerField() 21 press = models.ForeignKey(Press)
Press表:
Book表:

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。 键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。
1 # 聚合 2 from django.db.models import Avg, Max, Min, Count 3 4 print(models.Book.objects.all().aggregate(Avg('price'), Max('price'), Min('price'),Count('id'))) 5 ''' 6 result: 7 {'price__avg': 44.713333, 'price__max': Decimal('65.30'), 'price__min': Decimal('32.54'), 'id__count': 3} 8 '''
使用annotate()函数,对应数据库中的'group by'语句。
1 # 查询每一个出版社(Press)拥有的书籍(Book)数量 2 from django.db.models import Count 3 press_list = models.Press.objects.all().annotate(book_count=Count('book')) 4 [print(press_info, '出版社名称:{},书籍数量:{}'.format(press_info.name, press_info.book_count)) for press_info in press_list] 5 ''' 6 result: 7 Press object 出版社名称:长江出版社,书籍数量:2 8 Press object 出版社名称:电子工业出版社,书籍数量:1 9 Press object 出版社名称:清华大学出版社,书籍数量:0 10 ''' 11 # values 12 press_list = models.Press.objects.all().annotate(book_count=Count('book')).values('name', 'book_count') 13 [print(press_info) for press_info in press_list] 14 ''' 15 result: 16 {'name': '长江出版社', 'book_count': 2} 17 {'name': '电子工业出版社', 'book_count': 1} 18 {'name': '清华大学出版社', 'book_count': 0} 19 ''' 20 # value_list 21 press_list = models.Press.objects.all().annotate(book_count=Count('book')).values_list('name', 'book_count') 22 [print(press_info) for press_info in press_list] 23 24 ''' 25 result: 26 ('长江出版社', 2) 27 ('电子工业出版社', 1) 28 ('清华大学出版社', 0) 29 '''
from django.db.models import F
一、原来的filter只是单个字段和具体值之间的比较,使用F函数能够实现两个字段值之间的比较。
1 # 查询库存数量大于销售数量的书籍 2 [print(book.name) for book in models.Book.objects.all().filter(stock__gt=F('saleNumber'))] 3 ''' 4 result: 5 django深刻解析 6 spring源码解析 7 ''' 8 9 # 操做字符串 10 # 给每本书名后加上“当当网出售” 11 from django.db.models.functions import Concat 12 from django.db.models import Value 13 14 models.Book.objects.update(name=Concat('F("name")', Value("当当网出售"))) 15 16 # result:
二、F对象也支持使用算数运算:
list.filter(bread__gte=F('bcommet') * 2)
三、F对象中还能够写做“模型类__列名”进行关联查询:
list.filter(isDelete=F('heroinfo__isDelete'))
四、对于date/time字段,可与timedelta()进行运算:
list.filter(bpub_date__lt=F('bpub_date') + timedelta(days=1))
from django.db.models import Q
一、filter() 等方法中的关键字参数查询都是一块儿进行“AND” 的。 若是你须要执行更复杂的查询(例如OR语句),你可使用Q对象。
# 查询卖出数量大于10 或 价格小于50的书籍 且名字里包含‘spring’的书籍 [print(book.name) for book in models.Book.objects.filter(Q(saleNumber__gt=10) | Q(price__lt=50), name__contains='spring')] ''' result: spring源码解析当当网出售 '''
二、Q对象包括AND关系和OR关系,能够用&和|运算符进行链接。当以某个运算符链接两个Q对象时,就会产生一个新的Q 对象。 如:下面这段语句就产生了一个Q,这是用 "OR" 关系链接:
Q(question__startswith='Who') | Q(question__startswith='What')
三、每种查询函式(好比 filter(), exclude(), get())除了能接收关键字参数之外,也能以位置参数的形式接受一个或多个 Q 对象。若是你给查询函式传递了多个 Q 对象,那么它们彼此间都是 "AND" 关系。例如:
Poll.objects.get( Q(question__startswith='Who'), Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) )
四、也能够经过Q对象的children属性拼凑查询条件,传入条件进行查询:
q1 = Q() q1.connector = 'OR' # 链接方式 还有 'AND' q1.children.append(('id', 1)) q1.children.append(('id', 2)) q1.children.append(('id', 3)) models.Tb1.objects.filter(q1)
五、还能够将多个Q对象合并成一个Q对象进行查询:
con = Q() q1 = Q() q1.connector = 'OR' q1.children.append(('id', 1)) q1.children.append(('id', 2)) q1.children.append(('id', 3)) q2 = Q() q2.connector = 'OR' q2.children.append(('status', '在线')) con.add(q1, 'AND') con.add(q2, 'AND') models.Tb1.objects.filter(con)
1 try: 2 from django.db import transaction 3 with transaction.atomic(): 4 new_publisher = models.Publisher.objects.create(name="火星出版社") 5 models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id 6 except Exception as e: 7 print(str(e))
结果集修改器,一种提供额外查询参数的机制。
1 # 查询全部用户,并多查询出年龄是否大于20的一列 2 list = UserInfo.objects.all().extra(select={'gt20': 'age>20'}) 3 [print(u.gt20) for u in list] 4 ''' 5 result: 6 1 7 1 8 0 9 ''' 10 # 查询年龄大于20的用户 11 list = UserInfo.objects.all().extra(where=['age>20']) 12 # 等价于 13 list = UserInfo.objects.filter(age__gt=20)
执行原始sql并返回模型实例。
1 list = UserInfo.objects.raw('select * from UserInfo') 2 [print(i.name) for i in list]
惰性查询,返回rawQuerySet,只有在使用时才会真正执行。
直接执行自定义Sql(这种方式彻底不依赖model,前两种仍是要依赖于model)。
1 from django.db import connection 2 3 cursor = connection.cursor() 4 # 插入操做 5 cursor.execute("insert into UserInfo(name,age) values('郭敬明','99')") 6 # 更新操做 7 cursor.execute("update UserInfo set name='张三' where name='张大三'") 8 # 删除操做 9 cursor.execute("delete from UserInfo where name='张三'") 10 # 查询操做 11 cursor.execute('select * from UserInfo') 12 for u in cursor: print(u) 13 user_list = cursor.fetchall() # 读取全部 14 for u in user_list: print(u) 15 16 ''' 17 result: 18 (1, '张三', 21) 19 (2, '李四', 23) 20 (3, '王五', 19) 21 (4, '赵六', 40) 22 '''
现有以下模型:
class User(models.Model): nick_name = models.CharField(max_length=32) age = models.IntegerField()
首先咱们是知道 queryset.values 和 queryset.values_list 方法都是查询模型中指定字段,可是它们返回值的数据结构是不一样的。以下:
print(models.User.objects.values('nick_name', 'age')) # <QuerySet [{'nick_name': 'zhangsan', 'age': 12}, {'nick_name': 'lisi', 'age': 32}, {'nick_name': 'wangwu', 'age': 23}]> print(models.User.objects.values_list('nick_name', 'age')) # <QuerySet [('zhangsan', 12), ('lisi', 32), ('wangwu', 23)]>
能够看到,前者返回的是放着字典的 queryset ,然后者返回是放着元组的 queryset 。下面再看一下 queryset.only 方法:
print(models.User.objects.only('nick_name')) # (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user" LIMIT 21; args=() # <QuerySet [<User: User object (1)>, <User: User object (2)>, <User: User object (3)>]>
从 console 打印的 sql 能够看到, queryset.only 除了查询指定列还默认查询了主键,而返回值是对应模型对象。再看下面代码:
user_set = models.User.objects.only('nick_name') for user in user_set: print(user.age) ''' 12 32 23 (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user"; args=() (0.000) SELECT "api_user"."id", "api_user"."age" FROM "api_user" WHERE "api_user"."id" = 1; args=(1,) (0.000) SELECT "api_user"."id", "api_user"."age" FROM "api_user" WHERE "api_user"."id" = 2; args=(2,) (0.000) SELECT "api_user"."id", "api_user"."age" FROM "api_user" WHERE "api_user"."id" = 3; args=(3,) '''
能够看到,当咱们使用 only 中未指定的列时,这个列会即时加载。
user_set = models.User.objects.defer('nick_name') for user in user_set: print(user.age) print(user.nick_name) ''' (0.000) SELECT "api_user"."id", "api_user"."age" FROM "api_user"; args=() (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user" WHERE "api_user"."id" = 1; args=(1,) (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user" WHERE "api_user"."id" = 2; args=(2,) (0.000) SELECT "api_user"."id", "api_user"."nick_name" FROM "api_user" WHERE "api_user"."id" = 3; args=(3,) '''