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) 
原文地址:https://www.cnblogs.com/lixiang1013/p/7892307.html