Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/19.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 - Fatal编程技术网

Django如何通过连接获取相关对象?

Django如何通过连接获取相关对象?,django,django-models,Django,Django Models,我的型号与以下型号类似: class Reporter(models.Model): def gold_star(self): return self.article_set.get().total_views >= 100000 class Article(models.Model): reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE) total_views = mo

我的
型号与以下型号类似:

class Reporter(models.Model):
    def gold_star(self):
        return self.article_set.get().total_views >= 100000

class Article(models.Model):
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
    total_views = models.IntegerField(default=0, blank=True)
然后在其中一个
模板中
有一行:

{% if r.gold_star %}<img src="{% static 'gold-star.png' %}">{% endif %}
由django生成的查询

SELECT 
    `portal_reporter`.`id`,
    ...,
    CASE WHEN `portal_article`.`total_views` >= 0 THEN 1 ELSE 0 END AS `gold_star`
FROM
    `portal_reporter`
LEFT OUTER JOIN `portal_article`
ON (`portal_reporter`.`id` = `portal_article`.`reporter_id`)
WHERE
    ...
现在我只需要找到一种方法,在语句时如何生成类似的查询,但不使用
Case
/

EDIT3

如果我选择了稍微不同的策略,那么
django
选择了错误的连接类型:

query['article__id__gte'] = 0
reporters = Reporter.objects.filter(**query).select_related()
此代码生成类似的查询,但使用
内部联接
而不是所需的
左外部联接

SELECT 
    `portal_reporter`.`id`,
    ...,
FROM
    `portal_reporter`
INNER JOIN `portal_article`
ON (`portal_reporter`.`id` = `portal_article`.`reporter_id`)
WHERE
    ...

尝试注释新字段
gold\u star
,如果reporter的文章总浏览量超过100000次,则将其设置为1,如下所示:

from django.db.models import Case, When, Value, IntegerField

reporters = Reporter.objects.annotate(
    gold_star=Case(
        When(article__total_views__gte=100000, then=Value(1)), 
        default=Value(0),
        output_field=IntegerField()
    )
)

您可以保持模板代码不变。

您可以使用
select_related
()在相关表上执行联接

还有一个
prefetch_related
(),它使用
IN
子句通过额外的查询获取相关对象。文件中对差异进行了解释,但如下所示:

通过创建SQL联接并在select语句中包含相关对象的字段来选择与_相关的工作。因此,select_related将获取同一数据库查询中的相关对象。但是,为了避免跨“多”关系加入会导致更大的结果集,select_related仅限于单值关系-外键和一对一

另一方面,prefetch_-related对每个关系执行单独的查找,并在Python中执行“连接”。这允许它预取多对多和多对一对象,这是使用select_-related无法完成的,此外,select_-related还支持外键和一对一关系。它还支持对GenericRelation和GenericForeignKey的预取,但是,它必须限制为一组相同的结果。例如,仅当查询被限制为一种ContentType时,才支持预取GenericForeignKey引用的对象


当与
select_related()
一起使用时,您的方法确实创建了适当的联接,并且
django
只向数据库发送一个查询,万岁!无论如何,我只想将这两个表连接起来,因此在
语句时不使用
CASE。你能再详细一点吗?你用双下划线做连接。您可以简单地编写以下内容:
reporters=Reporter.objects.filter(article\uu total\u views\uu gte=100000)
我可以使用类似这样的内容:
filter(article\uu Reporter=Reporter.id)
?我得到
。。。不是'DeferredAttribute'
错误。您不能这样做,您必须有一个整数或
Reporter
的实例,而不是
Reporter.id
,但即使这样也没有意义。你到底想要什么?请看编辑2
from django.db.models import Case, When, Value, IntegerField

reporters = Reporter.objects.annotate(
    gold_star=Case(
        When(article__total_views__gte=100000, then=Value(1)), 
        default=Value(0),
        output_field=IntegerField()
    )
)