美文网首页Django+小程序
Django学习笔记:Models03 关系类型字段

Django学习笔记:Models03 关系类型字段

作者: Py_Bird | 来源:发表于2018-12-24 13:59 被阅读28次

    多对一(ForeignKey)

    多对一关系由外键实现,外键要定义在“多”的一方,如:

    models.ForeignKey(<主表>, ...)

    如果要关联的主表在另一个app中,要显式的指出:

    models.ForeignKey(’<app名称>.<主表>‘, ...)

     

    可创建自己关联自己的外键——比如,在评论系统中,一条评论可被多次引用自身并继续评论:

    class Comment(models.Model):

        title = models.Charfield(max_length=128)

        text = models.TextField()

        parent_comment = models.ForeignKey(’self’, on_delete=models.CASCADE)

        ...

    如果在子模型中存在多个外键指向同一个主模型,必须给他们加上不同的related_name,用于反向查询。

    外键字段在数据库中的列名是<外键名>_id,用来储存主表对象的id,因此,在得到主表id的情况下可以不调用外键而直接筛选:

    QuerySet = <外键表>.filter(<外键名>_id=<主表id>)

    #获得与“<主表id>=xxx的主对象”相关联的子对象

    多对一的字段参数

    on_delete=models.XXX

    当主对象被删除时,关联的子对象的操作(因为主键不能随意删除,外键可以直接删除)

    models.CASCADE:同时删除关联的子对象,Django默认

    models.PROTECT:阻止CASCADE删除关联的子对象,并弹出ProtectedError异常

    models.SET_NULL:将子对象的外键字段设为null(外键字段需设置null=True)

    models.SET_DEFAULT:将子对象的外键字段设为默认值(外键字段需设置default=’xxx’)

    models.DO_NOTHING:什么也不做

    models.SET():设置为一个传递给SET()的值或一个回调函数的返回值

    注:on_delete是Django2.0之后新增的必选项。

    related_name= 

    通过主对象反向引用子对象的通道名称,默认名称是<小写子模型名>_set。

    如:

    class Car(models.Model):

        factory = models.ForeignKey(

            Factory,      

            on_delete=models.CASCADE,

            related_name='car_by_factory',

        )

    此时Factory主表取出所有关联的Car对象:factory.car_by_factory.all()

    如果不想给外键设置反向关联名称,就用related_name=’+’或以+号结尾

    related_query_name= 

    主对象反向关联查询的名称,默认查询名称是<外键列>__<主表的某列>。

    如:

    class Tag(models.Model):

        article = models.ForeignKey(

            Article,

            on_delete=models.CASCADE,

            related_query_name="tag",

        )

        name = models.CharField(max_length=255)

    此时用tag作为查询名称:Article.objects.filter(tag__name="A")

    limit_choices_to={}

    限制外键能关联的对象,用于Django的表单模块和admin后台,可以传入字典、Q对象、一个返回字典或Q对象的函数。

    如:

    staff_member = models.ForeignKey(

        User,

        on_delete=models.CASCADE,

        limit_choices_to={'is_staff': True},

    )

    此时,表单模块的staff_member字段列表中只会出现is_staff=True的Users对象,对admin后台非常有用。

    to_field= 

    让外键关联到指定的字段上(默认关联到主键),该字段必须有unique=True属性。

    多对一的引用

    子对象引用主对象:

    <子对象>.<外键列>

    主对象引用子对象:

    <主对象>.<子表小写>_set

    如:

    <主对象>.<子表小写>_set.all()                          #所有关联子对象的集合

    <主对象>.<子表小写>_set.create(<子表字段>=’xxx’, ...)     #创建关联的子对象

    <主对象>.<子表小写>_set.count()                       #查询关联子对象的数量

    添加多对一关系:

    <子对象>.<外键列> = <主对象>

    <子对象>.save()

    删除多对一关系:

    <子对象>.<外键列> = None     #外键列要设为null=True

    多对一的查询

    查询子对象的集合:

    <子表>.objects.filter(<外键列>__<主表的某列>=’xxx’)

    #获得与“<主表的某列>=xxx的主对象”相关联的子对象

    查询主对象的集合:

    <主表>.objects.filter(<子表小写> __<子表的某列>=’xxx’)

    #获得与“<子表的某列>=xxx的子对象”相关联的主对象

    多对多(ManyToManyField)

    多对多字段可定义在任意一方,如:

    models.ManyToManyField(‘<主表>’)

    多对多字段不支持Django内置的validators验证功能。

    null参数对ManyToManyField多对多字段无效,设置null=True毫无意义。

    如果在子模型中存在多个多对多键指向同一个主模型,必须给他们加上不同的related_name,用于反向查询。

    采用默认中间表的数据库结构:

    <中间表id>  <多对多表>_id   <主表>_id

    默认中间表通过保存两张表的id进行关联

    采用自定义中间表并添加新字段的数据库结构:

    <中间表id>  <新字段1>  <新字段2>  <多对多表>_id   <主表>_id

    多对多字段的参数

    related_name= 

    主对象反向引用多对象时的名称,和多对一相同。

    related_query_name= 

    主对象反向关联查询的名称,和多对一相同。

    through= 

    自定义中间表,用于保存两表关系的附加数据,中间表要有两个外键字段分别指向关联的两个模型。

    through_fields=(<字段1>, <字段2>)

    当中间表有多个外键指向一个表的时候,用through_firlds指定中间表的两个连接字段,如:

    class Person(models.Model):

        name = models.CharField(max_length=32)

    class Group(models.Model):

        name = models.CharField(max_length=64)

        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表的外键

            Person,

            on_delete=models.CASCADE,

            related_name="membership_invites",

        )

        invite_reason = models.CharField(max_length=128)

    db_table= 

    设置中间表的名称,默认为<多对多字段名>_<主表名>_<一串哈希码>

    limit_choices_to={ }

    限制多对多键关联的对象,和多对一相同,对于用through定义中间表的字段无效。

     

    多对多的引用

    多对象引用主对象:

    <多对象>.<多键列>

    主对象引用多对象:

    <主对象>.<多表小写>_set

    添加多对多关系:(默认中间表)

    <多对象>.<多键列>.add(<主对象>)     #可同时添加多个主对象

    添加多对多关系:(自定义中间表)

    a = <主对象>

    b = <多对象>

    membership = <中间表>(<主表外键列>=a, <多表外键列>=b, <字段1>=’xxx’, <字段2>=’xxx’, ...)

    membership.save()

    #先创建主表和多表的实例,再创建中间表的连接关系

    #自定义中间表不能用add()、create()、remove()和set()操作对象的关系

    删除多对多关系:

    <多对象>.<多键列>.clear()

    获取中间表的附加数据:

    a = <主对象>

    b = <多对象>

    membership = <中间表>.objects.get(<主表外键列>=a, <多表外键列>=b)

    membership.<字段1>     #获取字段信息

    一对一(OneToOneField)

    反向关联的对象只有一个,多数用于从一个模型扩展出另一个模型的情况。

    一对一通过子对象访问关联的主对象:

    <子对象>.<一对一键>

    一对一通过主对象访问关联的子对象:

    <主对象>.<小写子模型名>

    注意返回的是单个对象而不是集合。

    相关文章

      网友评论

        本文标题:Django学习笔记:Models03 关系类型字段

        本文链接:https://www.haomeiwen.com/subject/qbfzkqtx.html