我正在尝试使用Django来显示来自多个模型的信息表,我不确定这样做的最佳实践是什么。这是我的models.py的简化版本:
from django.contrib.auth.models import User
class Widget(models.Model):
name = models.CharField(max_length=50)
pass
class Finished_Widget(models.Model):
user = models.ForeignKey(User)
thing = models.ForeignKey(Thing)
created = models.DateTimeField(editable=False)
这是一个非常简单的设置,用户和Widget通过未知数量的Finished_Widget对象连接。我想在html中显示的是Widget名称的实例列表和最近完成的小部件的日期。显然下面的代码不起作用,但希望它能说明我想要输出的数据。
{% for widget in widget_list %}
<p>{{ widget.name }}</p>
<p>{{ widget__Finished_Widget.latest.created }}</p>
{% endfor %}
我已经考虑过这个问题的许多不同方法,包括:
不幸的是,我无法完成任何这些工作,而且我不确定哪条甚至是正确的道路。
注意:我已经在SO上发现了很多关于这个问题的变化,这使得它非常接近欺骗,但它们似乎没有帮助我很多,因为需要缩小Finished_Widget列表到与用户ID匹配的用户ID,与Widget ID匹配,和仅匹配最新的。
答案 0 :(得分:2)
根据传递user
对象的需要更新了答案。
最简单的方法是在你的视图中处理这个问题,但它有问题。
for widget in widget_list:
widget.latest_finished_widget = widget.finished_widget_set.filter(user=request.user).latest('created')
{% for widget in widget_list %}
<p>{{ widget.name }}</p>
<p>{{ widget.latest_finished_widget }}</p>
{% endfor %}
虽然这段代码很容易编写,但每次迭代都会执行db查询。
一种快速解决方案称为查询分区。使用2个查询和python尽可能高效地填充反向关系,而无需转到SQL。
widgets = Widget.objects.filter(...)
finished_widget_map = dict(
[(x['thing__id'], x['created']) for x in
Finished_Widget.objects.filter(thing__in=widgets, user=request.user).values_list('thing__id', 'created').order_by('created')])
# this ensures we only select what we need, thing__id and the created column
# ordering by created will ensure only the last (latest) will appear in our dictionary
for widget in widgets:
widget.latest_finished_widget_created = finished_widget_map.get(widget.id, 'No Widget')
{% for widget in widgets %}
{{ widget.name }}
{{ widget.latest_finished_widget_created }}
{% endfor %}
但总有一些权衡。如果有许多Finished_Widgets python毫无意义地试图填充dict,那么这可能会很慢。
答案 1 :(得分:0)
嗯,我认为这里没有足够的信息来完全回答你的问题,但是只返回最近的Finished_Widget问题的一个简单解决方案就是在User模型中添加一个名为“latest_widget”的方法:
class User(models.Model):
#...
def latest_widget(self):
return self.widgets.all().order_by('-created')[0]
你可以在技术上将它添加到Finished_Widget模型中,尽管它没有多大意义。如果您正在使用Django的auth模块中的User模型,您可能希望对模型进行子类化以添加此功能。
一旦有了这个方法,从模板中调用它很简单。如果您有一个用户列表,例如,名为user_list,您可以显示每个用户和他/她的最新小部件,如下所示:
{% for uu in user_list %}
<p>
{{uu.username}}: {{uu.latest_widget.name}}
</p>
{% endfor %}