我有3个型号:
Product
模型相关联的模型Tag
Tag
模型相关联的模型Product
TagContent
模型相关联的模型Tag
(=一个内容仅链接到一个Tag
,一个Tag
可能包含一个或多个TagContent
1}})模型TagContent
适用于多语言:一个Product
可能有多个Tag
,但Tag
通过TagContent
显示在网页中:< / p>
class Tag(BaseModel):
name = models.CharField(max_length=60, unique=True, default='')
class TagContent(BaseTranslatableModel):
tag = models.ForeignKey(Tag, null=True, default=None)
slug = models.SlugField(max_length=60, unique=True)
locale = models.CharField(max_length=2) # (e.g. "fr")
class Produit(BaseModel):
name = models.CharField(max_length=60, unique=True)
tags = models.ManyToManyField(Tag, related_name='produits')
这就是我想要做的事情:在我的主页面中,客户选择语言。因此,我将根据客户选择的语言显示所有产品。
在我的主视图中,我想显示所有产品和所有标签,以便用户可以点击标签,然后我会过滤产品。
问题是标签应该用当前语言翻译。这意味着我必须使用当前区域设置过滤TagContent
,然后获取与Tag
相关联的所有TagContent
,然后获取与这些标记相关联的所有Product
这应该给出类似的东西(但它不起作用,因为外键在TagContent
,这是阻止我的主要问题):
Product.objects.filter(tags__in=
Tag.objects.filter(contents__in=
TagContent.objects.filter(langue__locale__exact=locale)
)
)
在模板模型中,我需要类似的东西:
{% for p in products %}
{% for tag. in p.tags.all %}
{{ tag.name }}
{% endfor %}
{% endfor %}
换句话说,我想做这个SQL查询:
SELECT tc.slug, tc.name
FROM produit p
JOIN produit_tag pt
ON pt.produit_id = p.id
JOIN tag t
ON pt.tag_id = t.id
JOIN tag_content tc
ON tc.tag_id = t.id
JOIN langue l
ON tc.langue_id=l.id
WHERE l.locale='fr'
- &GT; 2分钟写这个SQL,3小时我正在寻找解决方案。
答案 0 :(得分:1)
您可以使用此orm查询来获取产品:
products = Product.objects.prefetch_related("Tag", "TagContent").
filter(tags__tagcontent__locale="fr")
Django会像你手写的那样生成一个SQL。但是,一个SQL中的多个JOIN可能不是一个好主意,特别是如果连接的表非常大。考虑将查询分解为2可能会带来更好的性能(取决于您使用的数据库):
fr_tags = Tag.objects.filter(tagcontent__locale="fr")
products = Product.objects.filter(tags__in=fr_tags)
了解跨越关系的字段查找: https://docs.djangoproject.com/en/1.8/topics/db/queries/#lookups-that-span-relationships
答案 1 :(得分:0)
由于您已经拥有SQL查询,为什么不发送raw query。您只需将数据传递到模板即可。这将是类似的事情:
from django.db import connections
cursor = connection.cursor()
query = (""" SELECT tc.slug, tc.name
FROM produit p
JOIN produit_tag pt
ON pt.produit_id = p.id
JOIN tag t
ON pt.tag_id = t.id
JOIN tag_content tc
ON tc.tag_id = t.id
JOIN langue l
ON tc.langue_id=l.id
WHERE l.locale='fr' """)
cursor.execute(query)
data = []
for row in cursor.fetchall():
slug = row[0]
name = row[1]
data_point = {'name': name, 'slug': slug}
data.append(data_point)
答案 2 :(得分:0)
如果您没有使用PostgreSQL,这对您来说毫无用处,但我的前首席开发人员现在维护着django-pgviews项目。当您的SQL查询包含Django可能无法有效(或根本不能)执行的复杂连接时,它非常有用,您可以在自定义SQL视图中表示这些连接。你牺牲了Django的管理,但是你可以继续使用ORM来查询数据以便阅读。另请注意正在开发的django.contrib.postgres项目。