Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.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
获取Django中的相关对象以及如何对相关模型使用预取_Django_Django Models_Django Queryset_Prefetch_Django Debug Toolbar - Fatal编程技术网

获取Django中的相关对象以及如何对相关模型使用预取

获取Django中的相关对象以及如何对相关模型使用预取,django,django-models,django-queryset,prefetch,django-debug-toolbar,Django,Django Models,Django Queryset,Prefetch,Django Debug Toolbar,models.py class Press(models.Model): created = models.DateTimeField(editable=False) title = models.CharField(max_length=500, blank=True) slug = models.SlugField(max_length=600, blank=True, unique=True) def __str__(self): retu

models.py

class Press(models.Model):
    created = models.DateTimeField(editable=False)
    title = models.CharField(max_length=500, blank=True)
    slug = models.SlugField(max_length=600, blank=True, unique=True)

    def __str__(self):
        return self.title

class Scan(models.Model):
    press = models.ForeignKey(Press, related_name='scans', on_delete=models.CASCADE)
    created = models.DateTimeField(editable=False)
    title = models.CharField(max_length=300, blank=True)
    main_scan = models.ImageField(upload_to='press/scans', blank=True)

    def __str__(self):
        return self.title
views.py

class PressListView(ListView):
    model = Press
    context_object_name = "press"
    template_name = "press.html"

    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        context['press'] = 
Press.objects.prefetch_related(Prefetch('scans', 
queryset=Scan.objects.select_related('press')))
        return context
我想在网站前端实现的是列出所有的新闻和作为封面图片,每个新闻和图片都希望使用
scan
模型中的第一次
main\u scan
图像

我知道我可以将
models.ImageField
添加到
Press
model,但我不想-在管理中,我正在使用连接到Press model的扫描模型中的
admin.tablerinline

我知道有关于预回迁的文档,但可能我用错了,而且在模板的前端也做错了

问题是如何使它非常优化,性能最好,只需访问数据库一次

以前我是这样做的,它工作正常,但这会导致15个对象的15个SQL语句重复-通过使用django工具栏,我正在检查它的性能,这是非常低效的

{% for article in press %}
{{ article.title }}<br>
<img src="{{ MEDIA_URL }}{{ article.scans.all.0.main_scan }}" alt="">
{% endfor %}
{%用于新闻稿中的文章%}
{{article.title}}
{%endfor%}
我的目标是通过预回迁或其他方式达到DB一次。下面的代码不起作用,因此views.py是错误的,HTML也是错误的

{% for article in press %}
{{ article.title }}<br>
<img src="{{ MEDIA_URL }}{{ article.scans.main_image }}" alt="">
{% endfor %}
{%用于新闻稿中的文章%}
{{article.title}}
{%endfor%}
更新: 15份副本不见了。使用
Prefetch()


使用
Prefetch()
时,应将
分配给\u attr
,这是预取对象列表可用的属性名称。当前,多余的查询是访问字段的反向关系的结果,因为您分配了
相关的\u name='scans'

如果将属性重命名为类似于
scans\u list
,则可以访问预取的相关对象

press = Press.objects.prefetch_related(Prefetch(
    'scans',
    queryset=Scan.objects.select_related('press'),
    to_attr='scans_list'
))
然后在模板中,您将能够执行以下操作:

{% for article in press %}
{{ article.title }}<br>
<img src="{{ MEDIA_URL }}{{ article.scans_list.0.main_scan }}" alt="">
{% endfor %}
{%用于新闻稿中的文章%}
{{article.title}}
{%endfor%}
在您的回答中,您正在循环所有扫描-我要做的是列出所有新闻文章(ListView)每个新闻文章都有标题和一个图像-该图像是该新闻文章的第一次扫描-您正在做的-您列出了所有新闻文章,并且为每个文章列出了所有扫描。prefetch_related()得到了一个意外的关键字参数“to_attr”-得到了此错误(上下文['Press']=Press.objects.prefetch_related(Prefetch('scans',queryset=Scan.objects.select_related('press'))、to_attr='scans_list'))并且在模板中它可能不起作用,您不应该使用[0]-它应该像这样-{article.scans_list.0.main_Scan}而不是这个{{article.scans_list[0].main_Scan}-但首先,如果你能修复第一个错误。@Radek我弄乱了一个括号..现在修复了,因为我怀疑你不能使用:
{article.scans_list[0].main_scan}
-必须是这个
{article.scans_list.0.main_scan}
-然后你将得到
无法解析剩余部分:'[0].main_scan'from'article.scans_list[0].main\u scan'
错误,因此当我将您的更改为
{{article.scans\u list.0.main\u scan}}
-它开始工作-谢谢,这是最好的优化方法吗?它将19个查询削减为3个,这很完美,很好奇是否可以做其他事情:)-请修复模板标记,我将标记它已解决。没有问题,来自press模型的其他两个查询也是吗?