zoukankan      html  css  js  c++  java
  • python---django中orm的使用(4)字段,参数(on_delete重点)补充,一对多,一对一,多对多

    1.索引:

    普通索引:加快查找速度

    唯一索引:加快查找速度,唯一约束

    主键索引:加快查找速度,唯一索引,不为空

    class UserInfo(models.Model):
    
        username = models.CharField(
            null=False,     #不允许为空
            db_column='user',   #自定义列名,可以修改再数据库中的列名
            max_length=32,
            db_index=True,  #普通索引,只能加速查找
            # unique=True,    #约束索引,加速查找,唯一约束
            # primary=True,   #主键索引,加速查找,唯一约束,不为空
        )
        gender = models.BooleanField(
            default=True    #设置默认值
        )

    元类使用:

    用于生成联合索引,以及设置个别参数

        #元类信息
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "app01_un"
            # 联合索引
            # index_together = [
            #     ("username", "gender"),
            # ]
            # 联合唯一索引
            unique_together = (("username", "gender"),)
            #IntegrityError: columns user, gender are not unique
            # admin中显示的表名称
            verbose_name = "用户信息"

    2.一对多外键建立:

        el = models.ForeignKey(
            to="EmailInfo", #关联表
            to_field='id',  #关联列名
    db_constraint=True #是否在数据库该表中创建外键约束(外键功能查找等依旧存在,但是不具有约束功能) 比如:有约束时,邮箱id1-10,那么在该表中el也会是1-10,但是当false时,该el设置可以是任意,不受关联表的约束
         limit_choices_to=None, #在Admin或者ModelForm中显示数据时,提供限制后的数据展示
              --limit_choices_to={'id_gt':5}
              --limit_choices_to=lambda:{'id_gt':5}#或者lambda表达式 )
    class EmailInfo(models.Model):
        email = models.EmailField(
            null=False,
            db_index=True,
            unique=True,
        )
    外键关联表EmailInfo

    添加信息:

        #添加信息
        UserInfo.objects.create(
            username="张三",
            gender=True,
            el_id=1
        )
        UserInfo.objects.create(
            username="李四",
            gender=True,
            el_id=2
        )
      #因为唯一约束,是对姓名,性别一起约束,所以当不同时,是可以进行添加的 UserInfo.objects.create( username
    ="王五", gender=False, el_id=3 ) UserInfo.objects.create( username="王五", gender=True, el_id=3 ) UserInfo.objects.create( username="赵六", gender=True, el_id=4 ) EmailInfo.objects.create(**{'email': '46412454@qq.com'}) EmailInfo.objects.create(**{'email': '4641245454@qq.com'}) EmailInfo.objects.create(**{'email': '46412fwa454@qq.com'})

    对于外键,删除是是默认为级联删除,当删除一个,对应相关数据也会被删除,所以,我们有时候需要修改这一性质,在创建外键是使用on_delete即可

    对于on_delete的几种设置:

    def set_test():
        return 4
        el = models.ForeignKey(
            to="EmailInfo", #关联表
            to_field='id',  #关联列名
            null=True,
            default=2,
            #删除自己数据,对于被关联方,一点影响都没有
    
            #on_delete=None, #当关联的email数据被删除时候,该数据也会被删除,不存在
            #on_delete=models.CASCADE, #性质和None一样是默认删除
    #on_delete
    =models.DO_NOTHING, #当关联的数据被删除时,自己不受影响,什么事都不做,不会报错
    #on_delete
    =models.PROTECT, #关联保护,因为邮箱数据被用户表关联,所以该邮箱不允许被删除,并且触发ProtectError #Cannot delete some instances of model 'EmailInfo' because they are referenced through a protected foreign key: 'UserInfo.el'", <QuerySet [<UserInfo: UserInfo object>]>
    #on_delete=models.SET_NULL, #删除关联数据,自己被设置为null(前提字段需要设置为可空null=True) #对于测试models.SET_NULL时,我们需要先了解,对于数据库的基本字段设置,像null,max_length这些属性,我们需要重新去生成数据表, #对于on_delete等Django中的附属属性,我们可以动态修改,不需要重新生成数据表,所以如果我们开始并没有设置null=True(默认false),我们需要去重新生成数据表 #on_delete=models.SET_DEFAULT,#删除关联数据后,会将自己的数据设置为默认值,需要设置default属性
    #on_delete
    =models.SET(3) #和SET_DEFAULT相似,只不过不需要设置默认值,在SET()中可以直接设置 on_delete=models.SET(set_test) #和SET一样,只不过值设为了回调函数,需要将函数设为全局,可调用 )

     3.一对一:与一对多外键属性几乎一致,只是在unique上多加了true。两种实现:o和o1

    class User(models.Model):
        username = models.CharField(
            max_length=32,
            db_index=True,
        )
    
    class Tag(models.Model):
        title = models.CharField(
            max_length=16,
        )
    
        o = models.OneToOneField(
            to='User',
            to_field='id',
            on_delete=None,
            ###### 对于一对一 ######
            # 1. 一对一其实就是 一对多 + 唯一索引
            # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
            # 如下会在A表中额外增加一个c_ptr_id列且唯一:
        )
        o1 = models.ForeignKey(
            to='User',
            to_field='id',
            on_delete=None,
            unique=True,
        )

    4.多对多ManyToManyField

    class User(models.Model):
        username = models.CharField(
            max_length=32,
            db_index=True,
        )
    
        def __str__(self):
            return self.username
    
    class Tag(models.Model):
        title = models.CharField(
            max_length=16,
        )
    
        # m = models.ManyToManyField(to="User")
        # 使用ManyToManyField只能在第三张表中创建3列数据id(主键自增),外键1_id,外键2_id
        # m = models.ManyToManyField(
        #     to="User",
        #     related_name="tag", #反向查询是设置的字段名,替换(表名_set)默认是表名_set,这里设置后就可以简化了
        #     related_query_name="tg",  #反向查询是用于替换(表名)
        #     limit_choices_to=None,  #在admin中或者modelform中进行限制字段
        #     db_constraint=True   #同外键约束一致
        # )
    
        def __str__(self):
            return self.title

    自定义第三张表(查询方便):

    #自定义第三张表
    class UserToTag(models.Model):
        nid = models.AutoField(
            primary_key=True
        )
    
        u = models.ForeignKey(to="User")
        t = models.ForeignKey(to="Tag")
    
        ctime = models.DateField()
    
        #ManyToManyField中含有联合唯一
        class Meta:
            #联合唯一
            unique_together=[
                ('u', 't'),
            ]

     补充:through,through_fields.

    django除了能自动创建多对多的第三张表,同样也可以自定义创建多对多的第三张表,而且操作和管理扩展等难易程度要比自动创建的好许多。所以,在之后的models表结构中,推荐使用自定义的方式。并且加上through和through_fields

    class User(models.Model):
        username = models.CharField(
            max_length=32,
            db_index=True
        )class Tag(models.Model):
        title = models.CharField(
            max_length=32,
            db_index=True,
        )
    
        members = models.ManyToManyField(    
            User,
            through='UserToTag',
            through_fields=('u','t'),
        )
    class UserToTag(models.Model):
        u = models.ForeignKey(
            User,
            on_delete=models.CASCADE
        )
    
        t = models.ForeignKey(
            Tag,
            on_delete=models.CASCADE
        )

    操作:

        models.UserToTag.objects.create(
            u=models.User.objects.get(id=1),
            t=models.Tag.objects.get(id=2)
        )

    其他添加方法看:python---django中orm的使用(1)

    5.多对多---自查询:

    class User(models.Model):
        username = models.CharField(
            max_length=32,
            db_index=True
        )
        # 自关联(互粉操作),反向操作容易乱(各个表对他的反向操作都是User_set),最好加上related_name,以后最好都加上related_name
        # d = models.ManyToManyField("User",related_name='b')
  • 相关阅读:
    Java安装以及环境变量配置
    IPython绘图和可视化---matplotlib
    Tensorboard可视化(关于TensorFlow不同版本引起的错误)
    Tensorboard可视化
    关于Tensorflow安装opencv和pygame
    perl将json转换成xml
    cnblogs终于把以前内容的管理权还给我了~
    final评论2
    final评论1
    psp
  • 原文地址:https://www.cnblogs.com/ssyfj/p/8688561.html
Copyright © 2011-2022 走看看