一:元信息
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)