我目前正在用Django构建一个简单的应用程序,并试图确定一个好的模型设计。
第一种方法
在 Django 文档和我读过的许多博客文章中,建议使用 choice
关键字参数。这将在我的(简化的)名词模型中实现,如下所示:
class Noun(models.Model):
FEMININE = 0
MASCULINE = 1
NEUTER = 2
COMMON = 3
GENDER_TYPE = (
(FEMININE, "Feminine"),
(MASCULINE, "Masculine"),
(NEUTER, "Neuter"),
(COMMON, "Common"),
)
stem = models.CharField(max_length=200)
gender = models.IntegerField(choices=GENDER_TYPE, default=Noun.COMMON)
第二种方法
当我走过走廊,与一位数据库管理员朋友谈论他如何在数据库中指示枚举时,他承认有争议,但表示他会为每个枚举创建一个表,并通过外键引用它。此方法几乎完全映射到以下模型:
class Gender(models.Model):
short_name = models.CharField(max_length=1) # M, F, N, or C
description = models.CharField(max_length=20) # Masculine, Feminine, Neuter, or Common
class Noun(models.Model):
stem = models.CharField(max_length=200)
gender = models.ForeignKey(Gender, on_delete=models.CASCADE)
我试图权衡每种方法的相对优点。以下是我能辨别的利弊:
第一种方法
- 封装
- 无需导入"性别"模型
- 不需要在数据库中填充枚举值的额外步骤
- 在代码中更易于阅读:我不需要查看数据库即可查看有效值
第二种方法
- 更灵活:我可以一步将所有女性单词更改为男性,或者添加新的性别而无需修改名词表
- 逻辑由外键约束而不是代码强制执行,从而保持数据完整性
所以,我的问题:我是否错过了一些关于为什么一种方法无效的明显内容?如果两种方法都有效,哪种方法更好?
这两种方法都是有效的。要决定一个,你应该主要考虑两点:你有多少选择,以及它们在未来改变的可能性有多大。
因此,如果选择很少并且它们不太可能经常更改,请使用选择而不是外键 - 从性能的角度来看会更好。如果有很多选择或它们经常更改 - 请选择外键。
在这种情况下,对于性别,我会选择选择。即使它们将来发生变化 - 现有的也很可能不会受到影响。
您对这两种方法的优缺点的理解是正确的。在小型项目的情况下,您可以使用任何方法而不会出现任何问题。但是,如果您希望您的项目足够大,则应注意以下注释:
- 如果选择列表可能会随着时间的推移而增长,那么将其作为
Gender
模型会更容易。 - 如果选择列表无疑是常量的 - 请使用
gender
属性choices
字段。这将为您节省一些查询不必要的Gender
模型的时间。