小编Jos*_*rtz的帖子

Django:在字段上与在不同模型上存储模型属性

我对 Django 甚至数据库设计都比较陌生,我有一些想法希望由其他人来运行。这并不是一个具体的问题。我只是想看看其他人如何看待这些东西。

假设我们有一个应用程序到某个服务的模型。它包含您可能想象的应用程序包含的所有普通内容:

class Application(models.Model):
  first_name = CharField(max_length=255)
  last_name = CharField(max_length=255)
  date_of_birth = DateField()
  married = BooleanField()
  # ...other stuff
Run Code Online (Sandbox Code Playgroud)

好吧,这一切都很好。但是现在,想象一下您正在编写的 web 应用程序具有这样的功能,您可以部分完成您的应用程序,保存它,然后再回来使用它。一种方法是向上面的模型添加另一个属性:

complete = BooleanField()
Run Code Online (Sandbox Code Playgroud)

它有效,使用起来非常简单,但我真的不喜欢它,因为它混淆了应用程序的语义;它添加了与应用程序没有内在联系的信息。另一种方法是创建另一个模型来跟踪完整的应用程序:

class CompleteApplication(models.Model):
  application = ForeignKey(Application)
Run Code Online (Sandbox Code Playgroud)

我更喜欢这个,因为它保持Application清洁。但是,它确实存在混淆查询的缺点。以下是查询系统中所有完整应用的两种方式:

方法一:

completed_applications = Application.objects.filter(complete=True)
Run Code Online (Sandbox Code Playgroud)

方法二:

pks = CompleteApplication.objects.all().values_list("application__pk")
complete_applications = Application.object.filter(pk__in=pks)
Run Code Online (Sandbox Code Playgroud)

方法 2 是两行代码 vs. 一个又两个查询,而以前的一个就足够了,因此数据库性能将受到影响。

还有第三种方法:不是创建一个跟踪完整应用程序的模型,我们可以创建一个元数据模型来存储我们可能想要附加到Application模型的任何元数据。出于我们的目的,此模型可以包含一个跟踪完整性的字段。然而,这种方法还有一个好处是允许任意数量的元数据字段与每个应用程序相关联,而不需要为每个应用程序提供一个新的数据库表(如上面的方法 2 的情况)。

class ApplicationMeta(models.Model):
  application = ForeignKey(Application)
  complete = BooleanField()
Run Code Online (Sandbox Code Playgroud)

而且,为了完整性(双关语),要查询所有完整的应用程序,我们将使用以下语句:

completed_applications = Application.objects.all(applicationmeta__complete=True)
Run Code Online (Sandbox Code Playgroud)

很好很简单,就像方法一一样,但是查询肯定是对数据库的工作量更大。对于某些应用,这种方法还有另一个缺点。例如,假设我们要跟踪有关应用程序的一些附加信息:它们可以被确认,也可以被拒绝。然而,如果应用程序没有被证实,但这不是一定意味着它被拒绝:这可能是等待审核。此外,假设我们要跟踪确认日期和拒绝日期(当然,如果其中任何一个适用)。然后,我们的元数据模型变成如下:

class ApplicationMeta(models.Model):
  complete = BooleanField()
  confirmed = BooleanField() …
Run Code Online (Sandbox Code Playgroud)

django database-design django-models django-orm

5
推荐指数
1
解决办法
1073
查看次数