我有以下两个类:
class Incident(models.Model):
iid = models.IntegerField(primary_key=True)
person = models.ForeignKey('Person', on_delete=models.SET_NULL, null=True)
class Source(models.Model):
sid = models.IntegerField(primary_key=True)
incident = models.ForeignKey('Incident', on_delete=models.SET_NULL, null=True)
url = models.TextField(validators=[URLValidator()])
datereported = models.DateField(null=True, blank=True)
我想在事件中创建一个字段,该字段将提取相关来源的最小报告日期。这是在模型中完成,还是在模板中完成?不确定最佳实践是什么,或者在这种情况下如何执行。
这是在模型中完成,还是在模板中完成?
严格来说,模板应该不包含业务逻辑。它应该包含呈现逻辑。因此,它应该指定某些东西应该如何可见,而不是应该可见什么。因此,它实际上不属于模板层,只属于模型层。
您可以通过以下方式获得最小的datereported
:
from django.db.models importMin
class Incident(models.Model):
iid = models.IntegerField(primary_key=True)
person = models.ForeignKey('Person', on_delete=models.SET_NULL, null=True)
@property
def first_reporteddate(self):
return self.source_set.aggregate(first=Min('datereported'))['first']
这将忽略Source
s,datereported
设置为None
(因此,如果有多个源,则采用未None
的最小datereported
(。如果没有datereported
不等于None
的Source
,或者根本没有相关的Source
s,它将返回None
但是,因为空集的最小值被认为是NULL
的(在 SQL 中,或在 Python/Django 中None
(。
然后,您可以在模板中使用它,例如:
{{ some_incident.first_reporteddate}}
如果你想要整个对象,你可以使用self.source_set.order_by('datereported').first()
,它将为您提供最早的相关Source
实例。但这会对性能产生(相当(小的影响(需要更长的时间(。在这种情况下,Django 将首先将所有列提取到内存中。因此,如果您只需要一列,这将导致您执行一些无用的序列化(在数据库端(和反序列化(在 Python 端(。
为此可以使用模型的属性:
class Incident(models.Model):
iid = models.IntegerField(primary_key=True)
person = models.ForeignKey('Person', on_delete=models.SET_NULL, null=True)
@property
def first_datereported(self):
first_source = self.source_set.order_by('datereported').first()
if first_source:
return first_source.datereported
在模板或代码的任何其他部分中,您可以将first_datereported
用作普通模型的字段:
{{ incident_instance.first_datereported }}