我正在将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
的{{1}}),该字段显示上一次事件发生后发生了多少。由于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
)还是与Base managers documentation中的以下语句有关>
查询相关模型时不使用基本管理器。
或完全不同的东西。
高度赞赏任何指针。
答案 0 :(得分:1)
在大多数情况下,管理器(此处为EventManager
)返回的查询集不用作实例列表,而是用作查询定义。唯一的例外是调用Event.objects.all()
时。这是实际使用r
对象的唯一情况。在其他所有情况下,向字段中添加字段delta
都是浪费时间,因为它们根本没有使用过。
您可以做的是定义一个可以在类的实例上调用的方法,以根据请求进行任何计算:
class Event(models.Model):
def delta(self):
return django.utils.timezone.now() - self.t
您也可以使用此方法对模板进行排序。
另一种方法是在视图中添加您需要的任何计算字段(但再次注意,在模板中访问时,请注意不要修改查询集,否则将发出新查询,对象将重新实例化,并且您在视图中添加的所有字段都会丢失。