Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从Django模板中的特定相关对象查询数据_Python_Django_Django Models - Fatal编程技术网

Python 从Django模板中的特定相关对象查询数据

Python 从Django模板中的特定相关对象查询数据,python,django,django-models,Python,Django,Django Models,我试图使用Django来显示来自多个模型的信息表,我不确定这样做的最佳实践是什么。这是my 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.Foreign

我试图使用Django来显示来自多个模型的信息表,我不确定这样做的最佳实践是什么。这是my 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)
这是一个非常简单的设置,用户和小部件通过未知数量的完成的小部件对象进行连接。我想在html中显示的是小部件名称的实例列表和最近完成的小部件的日期。显然,下面的代码不起作用,但希望它能说明我希望输出的数据

{% for widget in widget_list %}
<p>{{ widget.name }}</p>
<p>{{ widget__Finished_Widget.latest.created }}</p>
{% endfor %}
{%用于widget_list%}
{{widget.name}

{{widget\uuuu Finished\u widget.latest.created}

{%endfor%}
我考虑了许多不同的方法来解决这个问题,包括:

  • 通过视图附加所需日期作为附加属性
  • 在视图中创建字典并在模板中调用
  • 使用“through”参数的ManyToManyField
  • 向小部件添加meta,调用最新完成的_小部件的创建日期
不幸的是,我没有能够做到这些,我也不知道哪一个,如果有的话,甚至在正确的道路上


注意:我已经在SO上发现了很多关于这个问题的变体,这使得这个问题非常接近于重复,但它们似乎对我没有多大帮助,因为需要将完成的小部件列表缩小到那些匹配用户ID、匹配小部件ID、仅匹配最新的小部件。

嗯,我认为这里没有足够的信息来完全回答您的问题,但对于只返回最新完成的_小部件的问题,一个简单的解决方案是在用户模型中添加一个称为“最新_小部件”的方法:

class User(models.Model):
    #...
    def latest_widget(self):
        return self.widgets.all().order_by('-created')[0]
从技术上讲,您可以将其添加到已完成的_小部件模型中,尽管这没有多大意义。如果您使用的是Django的auth模块中的用户模型,那么您可能希望对该模型进行子类化,以便添加此功能

一旦有了这个方法,从模板调用它就很简单了。如果您有一个用户列表,例如,称为user_list,则可以如下所示显示每个用户及其最新小部件:

{% for uu in user_list %}
<p>
    {{uu.username}}: {{uu.latest_widget.name}}
</p>
{% endfor %}
{用户列表%中uu的%

{{uu.username}:{{uu.latest_widget.name}

{%endfor%}
根据传入用户对象的需要更新了答案

在你看来,最简单的方法就是处理这个问题,但它也有它的问题

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 %}

不过,总有一些权衡。如果有许多已完成的小部件,python将毫无意义地尝试用它们填充dict,那么这可能会很慢。

如果我不够清楚,很抱歉,Walter,但我将遍历一个小部件列表,而不是用户,我将从最新的已完成的小部件对象访问“创建”字段,不是最新的Widget对象。他似乎在迭代
Widget\u列表
,这大概是
Widget
实例——因此它必须进入其中。尽管如此,你的想法还是行得通的:)编辑:浏览器刷新失败啊,是的,我现在明白了。嗯,对我来说,制定解决方案最有帮助的事情是查看一些示例数据(因为它存在于您的模型和数据库中)以及它在页面上的显示方式。Yuji,我想您可能无意中强调了我在这方面遇到这么多麻烦的原因。你能解释一下你从哪里得到“成品”吗?看起来可能是django模板语法的某些方面,我找不到相关文档?还是你认为我会在其他地方定义它?@IanWhalen,好问题!是的,django自动生成方便的方法“向后”检索关系——默认情况下:fieldname\u set。尽管如此,它还是很低效,正如您可能想象的那样,每个小部件有一个查询。如果您有一个对象,并且想要所有100个相关对象,而不是100个对象,每个对象都有一个您想要的相关对象,那么它更有用。PS:模板点表示法严格基于python,除了点表示法之外,没有特殊的模板语法:)它执行python dict查找、attr查找、索引查找,然后以静默方式失败。所以,如果有一种点表示法你不认识,那就是python dict键、attr或index!嘿,Yuji,我不想“取消回答”,但我意识到你的第一个建议有一个相当大的问题。“widget.finished\u widget\u set.latest”部分将返回整个数据库中最新的finished\u widget,而我需要它只显示当前经过身份验证的用户的最新信息。但是,由于无法在模板内传递参数,因此“widget.finished\u widget\u set(user=user).latest”将无法工作,这一事实阻止了我。这有意义吗?@IanWhalen:那么您必须通过视图在对象上设置一个属性(模型方法不应该处理请求)。尽管如此,我还是强烈建议我指出的第二种方法!更新的示例
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 %}