[django] ORM连表操作

文章链接:wupeiqi

  1. 连表

    class UserProfile(models.Model):
        user_info = models.OneToOneField('UserInfo')
        username = models.CharField(max_length=64)
        password = models.CharField(max_length=64)
    
        def __unicode__(self):
            return self.username
    
    
    class UserInfo(models.Model):
        user_type_choice = (
            (0, u'普通用户'),
            (1, u'高级用户'),
        )
        user_type = models.IntegerField(choices=user_type_choice)
        name = models.CharField(max_length=32)
        email = models.CharField(max_length=32)
        address = models.CharField(max_length=128)
    
        def __unicode__(self):
            return self.name
    
    
    class UserGroup(models.Model):
    
        caption = models.CharField(max_length=64)
    
        user_info = models.ManyToManyField('UserInfo')
    
        def __unicode__(self):
            return self.caption
    
    
    class Host(models.Model):
        hostname = models.CharField(max_length=64)
        ip = models.GenericIPAddressField()
        user_group = models.ForeignKey('UserGroup')
    
        def __unicode__(self):
            return self.hostname
    

    一对一
    类似一对一
    1、搜索条件使用 __ 连接
    2、获取值时使用 . 连接

    user_info_obj = models.UserInfo.objects.filter(id=1).first()
    print user_info_obj.user_type
    print user_info_obj.get_user_type_display()
    print user_info_obj.userprofile.password
     
    user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first()
    print user_info_obj.keys()
    print user_info_obj.values()
    

    多对多

    user_info_obj = models.UserInfo.objects.get(name=u'moke')
    user_info_objs = models.UserInfo.objects.all()
     
    group_obj = models.UserGroup.objects.get(caption='CEO')
    group_objs = models.UserGroup.objects.all()
     
    # 添加数据
    #group_obj.user_info.add(user_info_obj)
    #group_obj.user_info.add(*user_info_objs)
     
    # 删除数据
    #group_obj.user_info.remove(user_info_obj)
    #group_obj.user_info.remove(*user_info_objs)
     
    # 添加数据
    #user_info_obj.usergroup_set.add(group_obj)
    #user_info_obj.usergroup_set.add(*group_objs)
     
    # 删除数据
    #user_info_obj.usergroup_set.remove(group_obj)
    #user_info_obj.usergroup_set.remove(*group_objs)
     
    # 获取数据
    #print group_obj.user_info.all()
    #print group_obj.user_info.all().filter(id=1)
     
    # 获取数据
    #print user_info_obj.usergroup_set.all()
    #print user_info_obj.usergroup_set.all().filter(caption='CEO')
    #print user_info_obj.usergroup_set.all().filter(caption='DBA')
    
  2. 连表

    一对多:models.ForeignKey(其他表)
    多对多:models.ManyToManyField(其他表)
    一对一:models.OneToOneField(其他表)

    应用场景:

    一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
    例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。

    多对多:在某表中创建一行数据是,有一个可以多选的下拉框
    例如:创建用户信息,需要为用户指定多个爱好

    一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了
    例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据

    外键

    ForeignKey(ForeignObject) # ForeignObject(RelatedField)
        to,                         # 要进行关联的表名
        to_field=None,              # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
                - models.CASCADE,删除关联数据,与之关联也删除
                - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
                - models.PROTECT,删除关联数据,引发错误ProtectedError
                - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
                - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
                - models.SET,删除关联数据,
                  	a. 与之关联的值设置为指定值,设置:models.SET(值)
                  	b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
    	                def func():
    	                    return 10
    	
    	                class MyModel(models.Model):
    	                    user = models.ForeignKey(
    	                        to="User",
    	                        to_field="id"
    	                        on_delete=models.SET(func),)
    	                        
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
    		# 如:
            	- limit_choices_to={'nid__gt': 5}
                - limit_choices_to=lambda : {'nid__gt': 5}
    
                    from django.db.models import Q
                    - limit_choices_to=Q(nid__gt=10)
                    - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                    - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
                    
        db_constraint=True          # 是否在数据库中创建外键约束
        parent_link=False           # 在Admin中是否显示关联数据
    

    一对一

    OneToOneField(ForeignKey)
        to,                         # 要进行关联的表名
        to_field=None               # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
    
        	###### 对于一对一 ######
            # 1. 一对一其实就是 一对多 + 唯一索引
            # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
            # 如下会在A表中额外增加一个c_ptr_id列且唯一:
            	class C(models.Model):
                	nid = models.AutoField(primary_key=True)
                    part = models.CharField(max_length=12)
    
                class A(C):
                    id = models.AutoField(primary_key=True)
                    code = models.CharField(max_length=1)
    

    多对多

    ManyToManyField(RelatedField)
        to,                         # 要进行关联的表名
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
        	# 如:
            	- limit_choices_to={'nid__gt': 5}
                - limit_choices_to=lambda : {'nid__gt': 5}
    
                from django.db.models import Q
                - limit_choices_to=Q(nid__gt=10)
                - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
            # 做如下操作时,不同的symmetrical会有不同的可选字段
            	models.BB.objects.filter(...)
    
                # 可选字段有:code, id, m1
                      class BB(models.Model):
                          code = models.CharField(max_length=12)
                          m1 = models.ManyToManyField('self',symmetrical=True)
    
                # 可选字段有: bb, code, id, m1
                      class BB(models.Model):
                          code = models.CharField(max_length=12)
                          m1 = models.ManyToManyField('self',symmetrical=False)
    
        through=None,               # 自定义第三张表时,使用字段用于指定关系表
        through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
        	from django.db import models
    
            class Person(models.Model):
                name = models.CharField(max_length=50)
    
            class Group(models.Model):
                name = models.CharField(max_length=128)
                members = models.ManyToManyField(
                    Person,
                    through='Membership',
                    through_fields=('group', 'person'),
                )
    
            class Membership(models.Model):
                group = models.ForeignKey(Group, on_delete=models.CASCADE)
                person = models.ForeignKey(Person, on_delete=models.CASCADE)
                inviter = models.ForeignKey(
                    Person,
                    on_delete=models.CASCADE,
                    related_name="membership_invites",
                )
                invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # 是否在数据库中创建外键约束
        db_table=None,              # 默认创建第三张表时,数据库中表的名称
    
posted @ 2019-10-08 16:50  Moke丶青  阅读(246)  评论(0)    收藏  举报