表关系

表之间的关系都是通过外键来进行关联的。而表之间的关系

一对多

  1. 应用场景:比如文章和作者之间的关系。一个文章只能由一个作者编写,但是一个作者可以写多篇文章。文章和作者之间的关系就是典型的多对一的关系。
  2. 实现方式:一对多或者多对一,都是通过ForeignKey来实现的。 在多的那边设置
  3. 以文章和作者的案例进行讲解。

    1. class User(models.Model):
    2. username = models.CharField(max_length=20)
    3. password = models.CharField(max_length=100)
    4. class Article(models.Model):
    5. title = models.CharField(max_length=100)
    6. content = models.TextField()
    7. author = models.ForeignKey("User",on_delete=models.CASCADE)
  4. 那么以后在给Article对象指定author,就可以使用以下代码来完成:

    1. article = Article(title='abc',content='123')
    2. author = User(username='van',password='111111')
    3. # 要先保存到数据库中
    4. author.save()
    5. article.author = author
    6. article.save()
  5. 并且以后如果想要获取某个用户下所有的文章,可以通过article_set来实现。
    article_set这是在被引用外键的模型下Django自动创建的一个属性,如果这个名字不喜欢,可以在引用外键函数中指定参数related_name = "xxxx"
    示例代码如下:

    1. # article_set示例
    2. user = User.objects.first()
    3. # 获取第一个用户写的所有文章
    4. articles = user.article_set.all()
    5. for article in articles:
    6. print(article)

bulk=False

  1. # 用被引用外键的实例来保存引用外键的实例
  2. u = User.object.first()
  3. article = Article(title="bbb", content = "ccc")
  4. article.author = User.objects.first()
  5. u.article_set.add(article. bulk=False) #bulk=False
  • 使用bulk=False,那么Django会自动保存article,而无需article.save()
  • 注意的是:
    • 如果不用bulk=False,需要在执行add()前先aricle.save(),但是如果article.category被设置为空,会造成死锁(article实例保存需要user实例,user实例的article_set添加需要article实例)
    • 如果是该情景,建议 bulk=False

一对一

  1. 应用场景:比如一个用户表和一个用户信息表。在实际网站中,可能需要保存用户的许多信息,但是有些信息是不经常用的。如果把所有信息都存放到一张表中可能会影响查询效率,因此可以把用户的一些不常用的信息存放到另外一张表中我们叫做UserExtension。但是用户表User和用户信息表UserExtension就是典型的一对一了。
  2. 如果想要反向引用,那么是通过引用的模型的名字转换小写的形式进行访问。
  3. 实现方式:Django为一对一提供了一个专门的Field叫做OneToOneField来实现一对一操作。示例代码如下:

    1. class User(models.Model):
    2. username = models.CharField(max_length=20)
    3. password = models.CharField(max_length=100)
    4. # 这里有一个全小写的userextension属性,可以在引用参数使用related_name="xxx"更改
    5. # 可以User.userextension获得对象
    6. class UserExtension(models.Model):
    7. birthday = models.DateTimeField(null=True)
    8. school = models.CharField(blank=True,max_length=50)
    9. user = models.OneToOneField("User", on_delete=models.CASCADE)
  4. UserExtension模型上增加了一个一对一的关系映射。其实底层是在UserExtension这个表上增加了一个user_id,来和user表进行关联,并且这个外键数据在表中必须是唯一的,来保证一对一。

多对多

  1. 应用场景:比如文章和标签的关系。一篇文章可以有多个标签,一个标签可以被多个文章所引用。因此标签和文章的关系是典型的多对多的关系。
  2. 实现方式:Django为这种多对多的实现提供了专门的Field。叫做ManyToManyField。还示例代码如下:

    1. class Article(models.Model):
    2. title = models.CharField(max_length=100)
    3. content = models.TextField()
    4. tags = models.ManyToManyField("Tag",related_name="articles")
    5. class Tag(models.Model):
    6. name = models.CharField(max_length=50)
  3. 在数据库层面,实际上Django是为这种多对多的关系建立了一个中间表。这个中间表分别定义了两个外键,引用到articletag 两张表的主键。