我有以下两个课程:
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)
我想在事件中创建一个字段,该字段将提取相关来源的最小日期报告。这是最好在模型中还是在模板中完成?不确定什么是最佳做法,或者在这种情况下如何执行。
答案 0 :(得分:4)
这是最好在模型中还是在模板中完成?
严格来说,模板应该不包含业务逻辑。它应包含渲染逻辑。因此,它应指定如何可见,而不是什么可见。因此它并不真正属于模板层,而仅属于模型层。
您可以使用以下方法获得最小的datereported
:
from django.db.models import Min
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
,其中datereported
设置为None
(因此,如果有多个来源,则占用最小的datereported
不是None
)。如果没有Source
不等于datereported
的{{1}},或者根本没有相关的None
,则它将返回Source
,因为最小值空集的值被认为是None
(在SQL中,或在Python / Django中为NULL
)。
然后您可以在模板中使用它,例如:
None
如果需要整个对象,可以使用{{ some_incident.first_reporteddate }}
,它会为您提供与最早相关的self.source_set.order_by('datereported').first()
实例。但这对性能的影响很小(会花费更长的时间)。在这种情况下,Django将首先将 all 列提取到内存中。因此,如果您只需要 one 列,则将导致您进行了无用序列化(在数据库端)和反序列化(在Python端)。 / p>
答案 1 :(得分:3)
您可以为此使用模型的属性:
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 }}