侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论

Django - 优雅的声明两个模型之间的外键关联

barwe
2022-10-25 / 0 评论 / 0 点赞 / 1,089 阅读 / 1,252 字
温馨提示:
本文最后更新于 2023-06-07,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

个人更倾向于用明显 视觉含义 而不是内置的 id 字段来表示资源的主键。

下面定义了一个任务模型,它使用 name 字段作为主键:

class Task(models.Model):
    name = models.CharField(max_length=16, primary_key=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

当为模型显示设置主键后,Django 不再为数据表创建 id 字段。

一个任务属于某一个流程,一个流程包含多个任务,下面是一个流程模型,它同样使用 name 作为主键:

class Pipeline(models.Model):
    name = models.CharField(max_length=16, primary_key=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

现在我们为 Task 模型和 Pipeline 模型添加关联,在 Task 中定义外键:

class Task(models.Model):
    name = models.CharField(max_length=16, primary_key=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    pipeline = models.ForeignKey(
        Pipeline,
        to_field='name',
        on_delete=models.CASCADE,
        db_column='pipeline_name',
        related_name='tasks',
    )

通过models.ForeignKey()方法来定义一个外键,一个良好定义的外键应该提供一下五个参数:

  • 关联的模型,即当前模型的资源属于指定模型的某个资源
  • to_field: 关联模型的主键,以上,我们设置了 name 字段作为 Pipeline 模型的主键
  • on_delete: 删除关联资源时,级联删除它所属的所有本模型资源,按需设置
  • db_column: 数据表中用什么字段名来存储这个外键,默认可能是加 _id 后缀
  • related_name: 关联资源通过哪个属性来访问它关联的当前模型的所有资源,例如 pipeline.tasks

区分模型字段和数据表字段:

  • Task 模型实例的 pipeline 属性取出的是 Pipeline 模型的实例
  • 数据表 task 的 pipeline_name 列存储的是 pipeline 某个记录的 name 字段值

外键查询和反向查询:

  • task 通过 .pipeline 属性可以查询到它所属的 pipeline 资源
  • pipeline 通过 .tasks 属性可以查询到它包含的 tasks 资源
0

评论区