我是Django的新手,我在使用相关对象方面遇到了困难。在SQL方面这么简单似乎在这里非常棘手。
我有一个简单的数据库,如下所示:
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
class Language(models.Model):
code = models.CharField(max_length = 2)
name = models.CharField(max_length = 20)
class Translation(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
language = models.ForeignKey(Language)
title = models.TextField()
text = models.TextField()
class Article(models.Model):
pub_date = models.DateTimeField(verbose_name = "Publication date")
visible = models.BooleanField(default = False)
translations = GenericRelation(Translation)
这基本上是my previous question的后续行动。感谢Andrea Corbellini,上述模型看起来非常简洁明了。
现在我想在网页上显示这些文章。有一种当前语言,我只需要选择1)可见的文章和2)翻译当前语言。在SQL中,这意味着连接多个表并在单个查询中过滤它们。
如何在Django中做到这一点?这个问题实际上包括两个问题:如何进行快速查询以及如何将结果传递给模板。
我现在所做的是首先按可见进行过滤,然后按 pub_date 进行排序,然后遍历查询集,挑选具有正确翻译的文章,最后复制他们的字段进入上下文,因为模板引擎似乎并不了解如何访问相关对象。这是代码;它看起来很尴尬:
articles = Article.objects.filter(visible = True).order_by('-pub_date')
recent_news = []
for article in articles:
content = article.content(translation.get_language())
if not content.exists():
continue
content = content[0]
recent_news.append({
'pub_date': article.pub_date,
'title': content.title,
'abstract': content.text,
'text': content.text
})
context = { 'recent_news_list': recent_news }
这里有什么帮助就像一个元模型'或者某些中间件可以执行某些工作并缓存结果,因此请求某些语言的文章需要单个查询。但这是一个好方法吗?
答案 0 :(得分:1)
由于您需要发送到模板的所有信息都在翻译模型中,我会对该模型进行查询,并将其发送到模板。您在文章模型中唯一需要的是visible
字段,因此您可以对其进行过滤:
article = ContentType.objects.get_for_model(Article)
article_ids = Article.objects.filter(visible=True).values_list('id')
translations = Translation.objects.filter(content_type=article, object_id__in=article_ids)
context = {'recent_news_list: translations}
这只是三个查询:一个用于获取ContentType(虽然这可能会自动缓存),一个用于获取翻译,一个用于获取文章(而Django可能确实做第三个作为第二个子查询)。
但是,它总是会稍微复杂一点;这是您使用通用关系所付出的代价。我知道你的另一个问题确实有多种与翻译有关的类型,但是如果你能在没有做到这一点的情况下逃脱,那确实会更简单。