Django 在两个相关的模型中,哪一个应该包含关系的定义?
首先,是的:我读过Django的,但我仍然不完全清楚如何在实践层面上实现关系,特别是关系的层次结构Django 在两个相关的模型中,哪一个应该包含关系的定义?,django,database-design,django-models,model,relational-database,Django,Database Design,Django Models,Model,Relational Database,首先,是的:我读过Django的,但我仍然不完全清楚如何在实践层面上实现关系,特别是关系的层次结构 一对一 我知道如何建立一对一的关系。但是,在更概念化的层面上,哪个模型应该包含对另一个模型的引用?假设我有一个公民,还有一个护照。现在,很明显,一个公民只能有一个护照,反之亦然,但是,理想情况下,公民应该包含一个引用其护照的字段,还是护照模型应该包含对其所属公民的引用 多对多 为了简单起见,假设我有一个Person模型和一个Trip模型(Trip,比如去某处旅行)。许多人可以参加一次旅行。或者换句
公民
,还有一个护照
。现在,很明显,一个公民
只能有一个护照
,反之亦然,但是,理想情况下,公民
应该包含一个引用其护照的字段,还是护照
模型应该包含对其所属公民的引用
多对多
为了简单起见,假设我有一个Person
模型和一个Trip
模型(Trip
,比如去某处旅行)。许多人可以参加一次旅行
。或者换句话说:一个人
可以参加许多旅行
,而在任何一次旅行
,很多人
都可以参加。这看起来像是一种多对多关系,但是,再次强调,理想情况下,哪个模型应该包含关系的定义,带有行程
字段的人
,还是带有参与者
字段的行程?为什么?这有实际意义吗
谢谢。你应该具备的心智模式是父母和孩子。每种关系都有两种模式。因此,将其中一个视为父模型或主模型,将另一个视为子模型或次模型
注意:始终将“关系”字段放在子模型中
以下是我将如何解决您的问题:
对于第一个,我将有一个心智模型,公民是父母,护照是孩子
class Citizen(models.Model):
name = models.CharField(max_length=255)
info = models.TextField()
class Passport(models.Model):
owner = models.OneToOneField(Citizen)
unique_no = models.CharField(max_length=30, unique=True)
对于第二个问题,也要这样做。我会选择Person作为父模型,Trip作为子模型
class Person(models.Model):
name = models.CharField(max_length=255)
info = models.TextField()
class Trip(models.Model):
person = models.ManyToManyField(Person)
info = models.TextField()
如果您有sqlitebrowser
,您可以使用它打开数据库并检查根据您的模型创建了哪些表。然后,你会对Django如何看待你的模型有一个更清晰的认识。你应该拥有的心智模型是父母和孩子。每种关系都有两种模式。因此,将其中一个视为父模型或主模型,将另一个视为子模型或次模型
注意:始终将“关系”字段放在子模型中
以下是我将如何解决您的问题:
对于第一个,我将有一个心智模型,公民是父母,护照是孩子
class Citizen(models.Model):
name = models.CharField(max_length=255)
info = models.TextField()
class Passport(models.Model):
owner = models.OneToOneField(Citizen)
unique_no = models.CharField(max_length=30, unique=True)
对于第二个问题,也要这样做。我会选择Person作为父模型,Trip作为子模型
class Person(models.Model):
name = models.CharField(max_length=255)
info = models.TextField()
class Trip(models.Model):
person = models.ManyToManyField(Person)
info = models.TextField()
如果您有sqlitebrowser
,您可以使用它打开数据库并检查根据您的模型创建了哪些表。然后,您将更清楚地了解Django如何看待您的模型。这取决于您的业务逻辑。根据经验,我建议考虑一下管理应用程序。您希望如何添加新对象
添加新对象时,您希望如何添加相关对象
假设您有以下模型:
Citizen(models.Model):
name = models.CharField()
Passport(models.Model):
number = models.CharField()
citizen = models.OneToOneField('Citizen', related_name='passport')
当添加新的passport对象时,如果它还不存在,您可以添加新的公民。因为这在我看来不太符合逻辑,所以我将关系更改为:
Citizen(models.Model):
# other fields
passport = models.OneToOneField('Passport', related_name='citizen')
现在我们可以在admin中添加一个新的citizen对象,并在同一页面中添加相关的passport对象
如果您使用管理应用程序,这将引导您进行更符合人体工程学的设计
编辑:使用多对多示例展开
m2m关系的更好例子是StackOverflow——有问题和标签。一个问题有很多标签,标签有很多问题。假设模型如下所示:
Question(models.Model):
title = models.CharField()
body = models.TextField()
author = models.CharField()
tags = models.ManyToManyField('Tag', related_name='questions')
Tag(models.Model):
name = models.CharField()
我们为什么要质疑这种关系?这应该是非常合乎逻辑的-当创建一个新问题时,您希望为它设置标签。创建新标记时,您不关心与它相关的任何问题。您可以创建标记,稍后在创建问题时,将其与标记关联。
如果标签还不存在,您可以在添加新问题时从管理员处添加标签
我希望第二个例子更明显。这取决于您的业务逻辑。根据经验,我建议考虑一下管理应用程序。您希望如何添加新对象
添加新对象时,您希望如何添加相关对象
假设您有以下模型:
Citizen(models.Model):
name = models.CharField()
Passport(models.Model):
number = models.CharField()
citizen = models.OneToOneField('Citizen', related_name='passport')
当添加新的passport对象时,如果它还不存在,您可以添加新的公民。因为这在我看来不太符合逻辑,所以我将关系更改为:
Citizen(models.Model):
# other fields
passport = models.OneToOneField('Passport', related_name='citizen')
现在我们可以在admin中添加一个新的citizen对象,并在同一页面中添加相关的passport对象
如果您使用管理应用程序,这将引导您进行更符合人体工程学的设计
编辑:使用多对多示例展开
m2m关系的更好例子是StackOverflow——有问题和标签。一个问题有很多标签,标签有很多问题。假设模型如下所示:
Question(models.Model):
title = models.CharField()
body = models.TextField()
author = models.CharField()
tags = models.ManyToManyField('Tag', related_name='questions')
Tag(models.Model):
name = models.CharField()
我们为什么要质疑这种关系?这应该是非常合乎逻辑的-当创建一个新问题时,您希望为它设置标签。创建新标记时,您不关心与它相关的任何问题。您可以创建标记,稍后在创建问题时,将其与标记关联。
如果标签还不存在,您可以在添加新问题时从管理员处添加标签
我希望第二个例子更明显。这背后的理论被称为“最佳实践阶梯”,如果您想了解更多有关数据结构的信息,您应该查阅该阶梯
第三种形式告诉我们: