个人更倾向于用明显 视觉含义 而不是内置的 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 资源
评论区