Django2.0入门教程:多个数据模型间的关系


多表关联是模型层的重要功能之一, Django提供了一套基于关联字段独特的解决方案。那就是用:OneToOneField,ForeignKey,ManyToMany

先来区分一下什么是一对一、一对多、多对多
一对一:子表从母表中选出一条数据一一对应,母表中选出来一条就少一条,子表不可以再选择母表中已被选择的那条数据
一对多:子表从母表中选出一条数据一一对应,但母表的这条数据还可以被其他子表数据选择
共同点是在admin中添加数据的话,都会出现一个select选框,但只能单选,因为不论一对一还是一对多,自己都是“一”
多对多:
比如有多个孩子,和多种颜色、
每个孩子可以喜欢多种颜色,一种颜色可以被多个孩子喜欢,对于双向均是可以有多个选择
应用场景:
一对一(OneToOneField):一般用于某张表的补充,比如用户基本信息是一张表,但并非每一个用户都需要有登录的权限,不需要记录用户名和密码,此时,合理的做法就是新建一张记录登录信息的表,与用户信息进行一对一的关联,可以方便的从子表查询母表信息或反向查询
外键(ForeignKey):有很多的应用场景,比如每个员工归属于一个部门,那么就可以让员工表的部门字段与部门表进行一对多关联,可以查询到一个员工归属于哪个部门,也可反向查出某一部门有哪些员工
多对多(ManyToMany):如很多公司,一台服务器可能会有多种用途,归属于多个产品线当中,那么服务器与产品线之间就可以做成对多对,多对多在A表添加manytomany字段或者从B表添加,效果一致.

1、ForeignKey

模型示例

from django.db import models
classBlog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()
classAuthor(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()
classEntry(models.Model):
    blog = models.ForeignKey(Blog)
    authors = models.ManyToManyField(Author)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

classForeignKey
ForeignKey字段接受一个Model类作为参数,类型与被参照的字段完全相同:

 blog = models.ForeignKey(Blog)

ForeignKey.to_field
关联到的关联对象的字段名称。默认地,Django使用关联对象的主键。

blog = models.ForeignKey(Blog, to_field=Blog.name)

ForeignKey.db_constraint
Django Model的ForeignKey字段的主要功能是维护一个一对多的关系, 以进行关联查询.
只有在db_constraint=True时Django model才会在数据库上建立外键约束, 在该值为False时不建立约束.
默认db_constraint=True.
ForeignKey.related_name
这个名称用于让关联的对象反查到源对象.
如果你不想让Django 创建一个反向关联,请设置related_name 为 '+' 或者以'+' 结尾.
ForeignKey.related_query_name以ForeignKey.related_name作为默认值。

2、ManyToManyField

来自官网的例子

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)
    person = models.ForeignKey(Person)
    inviter = models.ForeignKey(Person, related_name="membership_invites")
    invite_reason = models.CharField(max_length=64)

ManyToManyField.through
Django会自动创建一个表来管理多对多关系,若要手动指定关联表则需要使用through关键字参数.
ManyToManyField.through_fields
上文示例中Membership有两个外键指向Person(person和inviter),这使得关联关系含混不清并让Django不知道使用哪一个。在这种情况下,必须使用through_fields明确指定Django应该使用哪些外键
through_fields接收一个二元组('field1','field2'),其中field1为指向定义ManyToManyField字段的模型的外键名称(本例中为group),field2为指向目标模型的外键的名称(本例中为person).
ManyToManyField.db_table
默认情况下,关联表的名称使用多对多字段的名称和包含这张表的模型的名称以及Hash值生成,如:memberShip_person_3c1f5
若要想要手动指定表的名称,可以使用db_table关键字参数指定.
others
下列API和ForeignKey中的同名API相同.
ManyToManyField.db_constraint
ManyToManyField.related_name
ManyToManyField.related_query_name

注意:

对于最新版本的django2.0在使用OneToOneField和ForeignKey时,需要加上on_delete参数。具体on_delete参数的详细用法请阅读下面的文章:Django2.0外键参数on_delete的使用方法