我正在使用Django 2.1进行项目。我的一个Models
(在下面的例子中称为Event
)与另一个Model
(下例中的Thing
)有多对一的关系。第一个模型应该具有我认为的计算字段。
为了显示:
class Thing(models.Model):
...
class Event(models.Model):
...
thing = models.ForeignKey(Thing, on_delete=models.CASCADE)
ts = models.DateTimeField(default=django.utils.timezone.now)
_delta = timedelta()
...
objects = EventManager()
@property
def delta(self):
return self._delta
@delta.setter
def delta(self, value):
self._delta = value
一个Event
应该有一个计算字段(timedelta
称为delta
),显示它发生在前一个事件之后多少。因为Event
的时间可以改变,所以在运行时计算这个timedelta
似乎更好,而不是将其存储在数据库中(保持数据库中最新的增量变得毛茸茸,例如,如果事件的时间以改变方式的方式发生变化事件序列,即一个事件“跳过”另一个事件。
所以我有一个Event
的自定义经理
class EventManager(models.Manager):
def get_queryset(self):
qs = super().get_queryset()
for r in qs:
r.delta = django.utils.timezone.now() - r.ts # fake calculation
return qs
当我现在“使用”它时,例如在模板中
{% for event in thing.event_set.all|dictsortreversed:"ts" %}
或者像这样的代码
events = thing.event_set.all()
然后没有设置event.delta
或events.delta
。即使看起来(我不知道如何证明)自定义管理器(EventManager
)被使用/调用。
我不确定问题是我不能更改查询集(即# fake calculation
的行是问题),或者这是否与Base managers documentation中的以下语句有关
查询相关模型时不使用基本管理器。
或者完全不同的东西。
任何指针都非常感谢。
在大多数情况下,管理器返回的查询集(此处:EventManager
)不是用作实例列表,而是用作查询定义。唯一的例外是调用Event.objects.all()
时。这是实际使用r
对象的唯一情况。在所有其他情况下,将字段delta
添加到它们是浪费时间,因为它们从未被使用过。
你可以做的是定义一个方法,可以在类的实例上调用它来根据请求进行任何计算:
class Event(models.Model):
def delta(self):
return django.utils.timezone.now() - self.t
您也可以使用此方法在模板中进行排序。
另一种方法是在视图中添加您需要的任何计算字段(但是在这里,您需要注意在模板中访问时不会修改查询集,否则会发出新查询,对象将被重新实例化,您在视图中添加的任何字段都将丢失。