zoukankan      html  css  js  c++  java
  • 如何理解数据库多个表之间的联系

    ## 一对多:

    1. 应用场景:比如文章和作者之间的关系。一个文章只能由一个作者编写,但是一个作者可以写多篇文章。文章和作者之间的关系就是典型的多对一的关系。

    2. 实现方式:一对多或者多对一,都是通过`ForeignKey`来实现的。还是以文章和作者的案例进行讲解。

    ```python

    class User(models.Model):

        username = models.CharField(max_length=20)

        password = models.CharField(max_length=100)

    class Article(models.Model):

        title = models.CharField(max_length=100)

        content = models.TextField()

        author = models.ForeignKey("User",on_delete=models.CASCADE)

    ```

    那么以后在给`Article`对象指定`author`,就可以使用以下代码来完成:

    ```python

    article = Article(title='abc',content='123')

    author = User(username='zhiliao',password='111111')

    # 要先保存到数据库中

    author.save()

    article.author = author

    article.save()

    ```

    并且以后如果想要获取某个用户下所有的文章,可以通过`article_set`来实现。示例代码如下:

    ```python

    user = User.objects.first()

    # 获取第一个用户写的所有文章

    articles = user.article_set.all()

    for article in articles:

        print(article)

    ```

    并且如果想要将文章添加到某个分类中。可以使用一下的方式:

    ```python

    category = Category.objects.first()

    article = Article(title='bbb',content='vvv')

    article.author = FrontUser.objects.first()

    category.article_set.add(article,bulk=False)

    ```

    * 使用`bulk=False`,那么Django会自动的保存article,而不需要在添加到category之前先保存article。

    * 或者是另外一种解决方式是,在添加到`category.article_set`中之前,先将`article`保存到数据库中。但是如果`article.category`不能为空,那么就产生一种死循环了,article没有`category`不能保存,而将article添加到`cateogry.artile_set`中,又需要article之前是已经存储到数据库中的。

    * 如果是上面的那种需求,建议使用`bulk=False`的解决方案。

    ## 一对一:

    1. 在Django中一对一是通过`models.OnetToOneField`来实现的。这个`OneToOneField`其实本质上就是一个外键,只不过这个外键有一个`唯一约束(unique key)`,来实现一对一。

    2. 以后如果想要反向引用,那么是通过引用的模型的名字转换为小写的形式进行访问。比如以下模型:

        ```python

        class FrontUser(models.Model):

            username = models.CharField(max_length=200)

        class UserExtension(models.Model):

            school = models.CharField(max_length=100)

            user = models.OneToOneField("FrontUser",on_delete=models.CASCADE)

        # 通过userextension来访问UserExtension对象

        user = FrontUser.objects.first()

        print(user.userextension)

        ```

        `UserExtension`的对象,可以通过`user`来访问到对应的user对象。并且`FrontUser`对象可以使用`userextension`来访问对应的`UserExtension`对象。

        如果不想使用Django默认的引用属性名字。那么可以在`OneToOneField`中添加一个`related_name`参数。示例代码如下:

        ```python

        class FrontUser(models.Model):

            username = models.CharField(max_length=200)

        class UserExtension(models.Model):

            school = models.CharField(max_length=100)

            user = models.OneToOneField("FrontUser",on_delete=models.CASCADE,related_name='extension')

        # 通过extension来访问到UserExtension对象

        user = FrontUser.objects.first()

        print(user.extension)

        ```

        那么以后就`FrontUser`的对象就可以通过`extension`属性来访问到对应的`UserExtension`对象。

    ## 多对多:

    1. 应用场景:比如文章和标签的关系。一篇文章可以有多个标签,一个标签可以被多个文章所引用。因此标签和文章的关系是典型的多对多的关系。

    2. 实现方式:`Django`为这种多对多的实现提供了专门的`Field`。叫做`ManyToManyField`。还是拿文章和标签为例进行讲解。示例代码如下:

    ```python

    class Article(models.Model):

        title = models.CharField(max_length=100)

        content = models.TextField()

        tags = models.ManyToManyField("Tag",related_name="articles")

    class Tag(models.Model):

        name = models.CharField(max_length=50)

    ```

    在数据库层面,实际上`Django`是为这种多对多的关系建立了一个中间表。这个中间表分别定义了两个外键,引用到`article`和`tag`两张表的主键。

  • 相关阅读:
    牛客网Java刷题知识点之方法覆盖(方法重写)和方法重载的区别
    牛客网Java刷题知识点之自动拆装箱
    安装Phoenix时./sqlline.py执行报错File "./sqlline.py", line 27, in <module> import argparse ImportError: No module named argparse解决办法(图文详解)
    Apache-kylin-2.0.0-bin-hbase1x.tar.gz的下载与安装(图文详解)
    Apache Kylin的架构特性
    Apache Kylin Cube 的存储
    Apache Kylin Cube 的构建过程
    Apache Kylin的核心概念
    中央网络安全和信息化领导小组办公室
    中国智慧城市建设投资联盟
  • 原文地址:https://www.cnblogs.com/pythonyeyu/p/10179717.html
Copyright © 2011-2022 走看看