Django反向查询
我正在尝试从父表查询到子表,并希望通过一次查询就能在父表中得到子表的结果。在我的例子中,我想在国际化(i18n)表之间建立关系,想要在一次查询中包含子表的行。
models.py
class main(models.Model):
slug = models.SlugField()
is_active = models.BooleanField(default=True)
site = models.ForeignKey(Site)
def __unicode__(self):
return self.slug
class main_i18n(models.Model):
main = models.ForeignKey(main)
language = models.CharField(max_length=2, choices=LANGUAGES)
title = models.CharField(max_length=50)
class Meta:
unique_together = (("language", "main"))
def __unicode__(self):
return self.title
我尝试了以下查询
a=main.objects.filter(is_active=True, main_i18n__language='en')
关系建立得很好,下面是我尝试打印查询时看到的内容
>>> a.query.__str__()
'SELECT `category_main`.`id`, `category_main`.`slug`, `category_main`.`is_active`, `category_main`.`site_id` FROM `category_main` INNER JOIN `category_main_i18n` ON (`category_main`.`id` = `category_main_i18n`.`main_id`) WHERE (`category_main_i18n`.`language` = en AND `category_main`.`is_active` = True )'
从查询中可以看出,它正确地进行了连接,但选择语句中没有包含列名。当我尝试使用循环访问main_i18n的数据时,无法访问。
抱歉我的英语不好,希望能找到帮助,
祝好,
---- 编辑:
下面是我目前使用的模板,最终我真的希望能创建一个单一的查询,并根据需要重新整理数据,以便在我的视图中列出。
<table class="homepage-listing">
<tr>
<td>
{# {% regroup list by main as rg_main %}#}
{% for obj in main %}
{# {% if obj.grouper != None %}#}
<div class="listing-block">
<a href="#" ><h3>{{ obj }}</h3></a>
<ul>
{% for s in obj.list %}
<li>{{ s.list_i18n_set.get }} </li>
{% endfor %}
</ul>
</div>
{# {% endif %}#}
{% endfor %}
</td>
</tr>
</table>
--- 编辑:
为了这个目的,我不得不使用额外的函数来构建一个单一的查询。我开始这样做,但变得有点复杂,我正在努力确保查询中的列名不是硬编码的,并且连接是正确的。有没有人能告诉我有没有更好的方法来写这个查询?
dict = Main.objects.extra(
select=
{
'main_title' : '%s.%s' % (MainI18n._meta.db_table, MainI18n._meta.get_field('title').verbose_name),
'list_title' : '%s.%s' % (ListI18n._meta.db_table, ListI18n._meta.get_field('title').verbose_name),
},
tables=[
'%s' % (MainI18n._meta.db_table),
'%s' % (List._meta.db_table),
'%s' % (ListI18n._meta.db_table),
],
where=[
'%s.%s=%s.%s' % (MainI18n._meta.db_table, 'main_id', Main._meta.db_table, 'id'),
'%s.main_id=%s.id' % (List._meta.db_table, Main._meta.db_table),
'%s.list_id=%s.id' % (ListI18n._meta.db_table, List._meta.db_table),
'category_listi18n.language="%s"' % (request.LANGUAGE_CODE)
]).select_related().filter(maini18n__language=request.LANGUAGE_CODE )
2 个回答
2
当你使用外键的时候,你需要通过一个叫做RelatedManager的东西来访问相关的数据。在你的例子中,你可以这样从main_i18n中获取main的数据:
>>> a=main.objects.get(id=1)
>>> i18n = a.main_i18n_set.get()
>>> i18n.language
u'en'
如果你需要对多个对象进行操作,可以这样做:
a = main.objects.filter(is_active=True, main_i18n__language='en')
for obj in a:
i18n = obj.main_i18n_set.get()
print i18n.language
这样的话,当然会对过滤出来的每个对象打印'en'。
1
你可以查询 MainI18N
这个内容:
MainI18N.objects.filter(main__is_active=True, language='en').select_related('main')
补充说明:你可以把这个放在一个自定义的查询方法里。快速的解决方案(虽然这样做不能进一步过滤查询结果)大概是这样的:
class MainQuerySet(QuerySet):
def translate(self, lang):
for obj in MainI18N.filter(language=lang, main__in=self).select_related('main'):
main = obj.main
main.i18n = obj
yield main