建立表关系

建立表关系

显然,关系型数据库的强大之处就在于将表相互关联,Django提供了定义三种最常见的数据库关系类型的方法:多对一、多对多和一对一。

一、表关系之多对一

1、多对一关系

要定义一个多对一关系,需要使用django.db.models.ForeignKey。您可以像使用任何其他字段类型一样去使用它:将其作为模型的类属性

# ForeignKey的参数:
1、to:所关联的模型类

2、to_field: 设置要关联表的字段
3、related_name: 此处暂且忽略,会在后续章节专门介绍
4、related_query_name: 此处暂且忽略,会在后续章节专门介绍
5、db_constraint:是否在数据库中创建外键约束,默认为True。

6、on_delete:当删除关联表中的数据时,当前表与其关联的行的行为,值可以是如下
  models.CASCADE
  删除关联数据,与之关联也删除

  models.DO_NOTHING
  删除关联数据,引发错误IntegrityError

  models.PROTECT
  删除关联数据,引发错误ProtectedError

  models.SET_NULL
  删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)

  models.SET_DEFAULT
  删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)

  models.SET(值)
  删除关联数据,与之关联的值设置为指定值

   models.SET(可执行对象)
  删除关联数据,与之关联的值设置为可执行对象的返回值,例如
   def func():
       return 10

   class MyModel(models.Model):
       user = models.ForeignKey(
            to="User",
            to_field="id",
            on_delete=models.SET(func)
       )

例如:

from django.db import models

class Manufacturer(models.Model):  # 汽车制造商
    # ...
    pass

class Car(models.Model):  # 汽车
    manufacturer = models.ForeignKey(to=Manufacturer, on_delete=models.CASCADE)
    # ...

建议(但不是必需的)ForeignKey字段的名称是模型的名称、小写(如上述manufacturer),这么做是为了在后期进行查询操作时方便自己识别。当然,你想叫什么就叫什么。例如:

class Car(models.Model):
    company_that_makes_it = models.ForeignKey(
        Manufacturer,
        on_delete=models.CASCADE,
    )
    # ...

*2、惰性关系*

上述关联关系的建立,由于ForeignKey的第一个位置参数是模型类,所以模型Car必须在Manufacturer之后,若想排除先后顺序带来的困扰,即需要创建与尚未定义的模型类的关系,可以将ForeignKey的第一个参数换成字符串形式,如下所示,这种定义关系的形式,称之为惰性关系

from django.db import models

class Car(models.Model):
    manufacturer = models.ForeignKey('Manufacturer', on_delete=models.CASCADE)
    # ...

class Manufacturer(models.Model):
    # ...
    pass

*3、自关联*

class Comment(models.Model):
    # 评论者
    user=models.ForeignKey(to='User',to_field='nid',on_delete=models.CASCADE)
    # 评论的文章
    article=models.ForeignKey(to='Article',to_field='nid',on_delete=models.CASCADE)
    # 评论的内容
    content=models.CharField(max_length=255)
    # 评论时间
    create_time=models.DateTimeField(auto_now_add=True)
    # 自关联
    parent_comment=models.ForeignKey(to='self',on_delete=models.CASCADE,null=True)

*4、其他*

# 1、数据库表示:
默认情况下,在数据库层面,django会在ForeignKey的字段后加后缀“_id”,即上述模型字段manufacturer对应的数据库表字段为manufacturer_id(我们可以用过db_column选项来进行自定义)

但是,我们在操作模型时只需要基于模型字段名字即可,只有在编写原生sql时才需要考虑数据库里的字段。

# 2、db_index
django会自动为ForeignKey字段创建索引,可以指定db_index=False来禁用此功能。

如果我们创建外键的目的是为了一致性而不是链接,或者你需要使用自定义的部分或多列索引,那么需要将db_index设置为False

# 3、ForeignKey的其他详细参数
https://docs.djangoproject.com/en/3.0/ref/models/fields/#arguments

二、表关系之多对多

*1、多对多关系*

定义多对多关系,需要使用ManyToManyField,您同样可以像使用任何其他字段类型一样去使用它:将其作为模型的类属性

# ManyToManyField参数:
1、to:所关联的模型类

2、to_field: 设置要关联表的字段
3、related_name: 同ForeignKey,此处暂且忽略,会在后续章节专门介绍
4、related_query_name: 同ForeignKey,此处暂且忽略,会在后续章节专门介绍
5、db_constraint:是否在数据库中创建外键约束,默认为True。
6、db_table: 默认创建第三张表时,数据库中该表的名称。

7、symmetrical:默认为True,此处暂且忽略,会在后续章节专门介绍
8、through: 详见本节"3、多对多额外的字段:中间模型"
9、through_fileds:详见本节"3、多对多额外的字段:中间模型"

# MannyToMany的其他详细参数:https://docs.djangoproject.com/en/3.0/ref/models/fields/#manytomany-arguments

例如

from django.db import models

class Topping(models.Model): # 馅料
    # ...
    pass

class Pizza(models.Model): # 披萨
    # ...
    toppings = models.ManyToManyField(Topping)

# 数据库表示:
在幕后,Django创建一个中间连接表来表示多对多关系。默认情况下,此表名是:包含该字段的模型的表名_多对多字段的名称。可以使用db_table选项手动设置连接表的名称。

建议(但不是必须)ManyToMany的字段名称(上例中的toppings)是一个关联的模型类名字的复数形式,用于描述相关模型对象集。

针对ManyToMany字段,只要不是同时放入两个模型中,在哪个模型中创建并不重要,但是通常情况下我们需要考虑逻辑上的通顺已经后期的使用方便,字段与类是一个从属关系,toppings字段在类Pizza里,我们可以说Pizza拥有toppings,翻译一下就是披萨有馅料,显而易见这比在Topping类里放入MannyToMany字段,逻辑上更通顺,从而使得后期的使用更为方便

*2、惰性关系*

同ForeignKey一样

*3、多对多额外的字段:中间模型*

111

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇

You cannot copy content of this page