如何在 Django 中构建模型?
Posted
技术标签:
【中文标题】如何在 Django 中构建模型?【英文标题】:How to structure models in Django? 【发布时间】:2021-04-26 14:32:57 【问题描述】:我正在使用 Python(3.7) 和 Django(3) 开发一个项目,我必须在其中创建一些模型来存储报告。有 4 种不同的模型来表示每种类型的报告,只有 2 个公共字段(RequestId
、InstCode
),但其余字段不同。最后,我必须在主页上显示最近的 10 份报告(来自所有模型的混合)。
以下是我目前实现模型的方式:
来自models.py
:
class DistributionReport(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
Currency = models.CharField(max_length=3, blank=False)
Denomination = models.IntegerField(blank=False, default=0)decimal_places=2)
date = models.DateField(default=datetime.date.today)
class Meta:
verbose_name = 'Distribution Report'
def __str__(self):
return self.RequestId
class ExpenditureReport(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
StaffExpenditure = models.DecimalField(max_digits=12, decimal_places=2)
Month = models.IntegerField(blank=False, default=0)
Quarter = models.IntegerField(blank=False, default=0)
Year = models.IntegerField(blank=False, default=0)
class Meta:
verbose_name = 'Expenditure Report'
def __str__(self):
return self.RequestId
class StorageReport(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
Currency = models.CharField(max_length=5, blank=False)
Denomination = models.IntegerField(blank=False, default=0)
date = models.DateField(default=datetime.date.today)
class Meta:
verbose_name = 'Processing Report'
def __str__(self):
return self.RequestId
class AssetsReport(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
AssetClassificationId = models.IntegerField(blank=False, default=0)
VaultCapacity = models.DecimalField(max_digits=10, decimal_places=2)
Year = models.IntegerField(blank=False, default=0)
HalfOftheYear = models.IntegerField(blank=False, default=0)
class Meta:
verbose_name = 'Assets Report'
def __str__(self):
return self.RequestId
构建这些模型的最佳方法是什么,以便我可以查询最近的报告(可以是任何类型)?
【问题讨论】:
我可以看到 2 种可能性:1)创建一个使用 generic foreign relations 到不同报表模型的基本报表类或 2)使用 django polymorphic 进行模型继承 【参考方案1】:查看标准化的工作原理,因为所有模型都有 2 个公共字段,假设您有一个名为 Report 的表,它具有字段 RequestId
和 InstCode
。现在可以说您所有其他模型都处于XYZReport is a Report
类的关系中。
您可以使用 OneToOne 字段来实现这一点,如下所示:
class Report(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
DISTRIBUTION = 'DI'
EXPENDITURE = 'EX'
STORAGE = 'ST'
ASSETS = 'AS'
REPORT_TYPE_CHOICES = [
(DISTRIBUTION, 'Distribution Report'),
(EXPENDITURE, 'Expenditure Report'),
(STORAGE, 'Storage Report'),
(ASSETS, 'Assets Report'),
]
report_type = models.CharField(
max_length=2,
choices=REPORT_TYPE_CHOICES,
default=DISTRIBUTION,
)
# Any more common fields
class DistributionReport(models.Model):
report = models.OneToOneField(
Report,
on_delete=models.CASCADE,
related_name = 'distribution_report'
)
# Other fields
# Other Report models in similar fashion
现在,每当制作任何类型的报告对象时,也可以制作Report
的对象并将其分配给模型的报告属性。保存这两个模型,还可以确定 Report 实例的报告类型,将相关的 report_type 添加到报告实例中,如下所示:
report.report_type = Report.DISTRIBUTION # In case of Distribution Report
要确定 Report 的实例是否属于特定类型:
report.report_type == report.DISTRIBUTION # will get whether Report is a DistributionReport
要获取特定类型对象,请使用 OneToOne 字段中设置的相关名称:
distribution_report = report.distribution_report
【讨论】:
以上是关于如何在 Django 中构建模型?的主要内容,如果未能解决你的问题,请参考以下文章
Django - 如何构建适合的中间 m2m 模型? / 最佳实践