30)django-ORM(元信息,级联删除,正反向操作,连表查询优化)
一:元信息
class User(models.Model): name=models.CharField(max_length,index=True) email=model.CharField(max_length,index=True) class meta: db_table="table_name"#定制表名,默认是app名_表名 #联合索引 index_together=[ ("name","email"), #联合索引支持最左前缀模式(上面单独索引可以不用建立,但是要考虑使用场景。因为单独最后一个字段查询是不能命中) #select * from where name="xx" 可以命中索引 #select * from where name="xx" and emial="XX"可以命中索引 #select * from where emial="XX" 不能命中索引 #所以这是有代价,最后一个不能命中索引 ] #联合唯一索引,和联合索引又加了限制唯一 unique_together=[()] #admin中显示表的名称 verbose_name #verbose_name加s verbose_name_plural verbose_name_plural="上课记录" django-admin中显示的是:上课记录s django admin先经过modelform验证,通过了再到model
二:外键级联删除(on_delete属性)
class userType(models.Model); name=models.CharField(max_length=32) class user(models.Model); name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) ... (to="UserType",to_field="id") #delte from UserType where id=1 #原生sql直接报错 UserType.objects.filter(id=1).delete() #默认也会把User表里关联的数据全部删除 #某个场景可以删除,某些不能删除 (to="UserType",to_field="id",on_delete=models.CASCAN)
三:正反向操作
#正反向操作 # 一对多正向操作 # v=User.objects.all() # for item in v: # item.name # item.pwd # item.ut.name #User.objects.all().value("user","ut__name") # 一对多反向操作 v=UserType.objects.all() for item in v: item.name item.id item.user_set.all() # 所有与之关联的User对象 UserType.objects.all().values("name","user__pwd")#通过表名和_返回查询 #上面通过表名反向查找,能不能换个名字 ut=models.ForeignKey(to="UserType",to_field="id",related_name='b',related_query_name='a')#一对多正向操作,这个b可以代替(表名_set)反向操作.related_name='b',related_query_name='a'通过用不到,适用场景自关联 # 一对多反向操作 v=UserType.objects.all() for item in v: item.name item.id item.user_set.all() # 所有与之关联的User对象 ==item.b.all() UserType.objects.all().values("name","user__pwd")#通过表名返回查询 ==a_pwd
四:性能优化(联表查询)
#性能优化(联表查询) 1)select_related #如果数据库中有10条数据, users=models.User.objects.all()#仅仅是用户表中的数据 for row in users: print(row.user,row.pwd,row.ut_id) print(row.ut.name) #会再发一会SQL请求 #上面相当于做了11次查询,效率不高。,如果外键很多,就跨表执行多次。 users=models.User.objects.all().values('user','pwd','ut__nmae') #只执行一次。但是取到是字典。如果非要是对象。 #再优化 users=models.User.objects.all().select_related() 也是只执行一次,就都取到数据了。但是如果有些不需要跨表(多个外键的时候,只取一个一个外键),可以加参数(这里只能加与外表关联的字段) users=models.User.objects.all().select_related(“ut”) 2)prefetch_related #上面如果联表联的多了也不太好,django提供prefetch_related 如:100条数据和3条业务关联了 users=models.User.objects.filter(id__gt=30).prefetch_related(“ut”) #这个不会做联表查询,会做两次sql请求。它会: #select * from user where id>30 #获取上一步中所有的ut_id=[1,2,3] #select * from user_type where id in [1,2] 上面都放在内存里面了。django会把两张表里的数据做自动关联。 for row in users: print(row.user,row.pwd,row.ut_id) print(row.ut.name)