中介模型:
针对多对多关系,虽然可以自动创建关联表,但是需求是想要加入一些字段信息呢,这就需要自己手动建关联表了
对于这些情况,Django 允许你指定一个中介模型来定义多对多关系。 你可以将其他字段放在中介模型里面。源模型的ManyToManyField 字段将使用through 参数指向中介模型
models
1 from django.db import models 2 3 class Person(models.Model): 4 name = models.CharField(max_length=128) 5 6 def __str__(self): 7 return self.name 8 9 class Group(models.Model): 10 name = models.CharField(max_length=128) 11 members = models.ManyToManyField(Person, through=‘Membership‘) # through 指定关系表 12 13 def __str__(self): 14 return self.name 15 16 class Membership(models.Model): 17 person = models.ForeignKey(Person) # 外键写上 18 group = models.ForeignKey(Group) # 外键写上 19 date_joined = models.DateField() # 需求添加的额外外键 20 invite_reason = models.CharField(max_length=64) # 需求添加的额外外键
注意事项:
1 绑定关系的时候,与普通的多对多字段不同,你不能只创建 Person和 Group之间的关联关系,你还要指定 Membership模型中所需要的所有信息;而简单的add、create 和赋值语句是做不到这一点的。 2 所以,你只实例化的时候,通过create来创建 3 m2 = Membership.objects.create(person=paul, group=beatles, 4 ... date_joined=date(1960, 8, 1), 5 ... invite_reason="Wanted to form a band.") 6 7 8 clear() 方法却是可用的。它可以清空某个实例所有的多对多关系:beatles.members.clear() 9 # Note that this deletes the intermediate model instances 10 Membership.objects.all() 11 []
查询优化:select_related
select_related就是join表,当成了一个表的时候for循环每次循环只会是一次
1 # 查询 主键等于2的文章的所属分类名称 2 obj = ret=models.Article.objects.filter(nid=2) 一次 3 for i in obj: 4 i. category.title # 每次打开2张表 5 6 7 # ret=models.Article.objects.filter(nid=2).values("category__title") 一次数据库 8 # print(ret) 9 10 11 # select_related 就是join一张表,left inner join是一样的效果,以左边为主 right join,以右边为主 12 obj_list=models.Article.objects.select_related("user").select_related("category").all() # 可以join多章表,也可以写在一个里面,逗号隔开 13 for obj in obj_list: # 14 print(obj.category.title)。# 每次打开一张表
extra 函数
语法格式:
extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
有些情况下,Django的查询语法难以简单的表达复杂的 WHERE 子句,extra可以指定一个或多个 参数,例如 select, where or tables. 这些参数都不是必须的,但是你至少要使用一个!
1 select:简单查询 2 queryResult=models.Article.objects.extra(select={‘is_recent‘: "create_time > ‘2017-09-05‘"}) 3 结果集中每个 Entry 对象都有一个额外的属性is_recent, 它是一个布尔值,表示 Article对象的create_time 是否晚于2017-09-05. 4 5 article_obj=models.Article.objects 6 .filter(nid=1) 7 .extra(select{"standard_time":"strftime(‘%%Y%%m%%d‘,create_time)"}).values("standard_time","nid","title") 8 print(article_obj) 9 # <QuerySet [{‘title‘: ‘MongoDb 入门教程‘, ‘standard_time‘: ‘2017-09-03‘, ‘nid‘: 1}]> 10 11 12 参数之where / tables:简单条件查询 13 您可以使用tables手动将表添加到SQL FROM子句,where和tables都接受字符串列表 14 queryResult=models.Article.objects.extra(where=[‘nid in (1,3) OR title like "py%" ‘,‘nid>2‘]) 15 ## table连接其它表 16 # SELECT * FROM myapp_book, myapp_person WHERE last = author_last 17 Book.objects.all().extra(table=[‘myapp_person‘], where=[‘last = author_last‘]) # 加from后面