使用 django ORM 进行高级选择

Posted

技术标签:

【中文标题】使用 django ORM 进行高级选择【英文标题】:Advanced select with django ORM 【发布时间】:2015-07-15 04:53:18 【问题描述】:

我正在使用以下模型:

class Topping(models.Model):
    name = models.CharField(max_length=30)

class Pizza(models.Model):
    name = models.CharField(max_length=50)
    toppings = models.ManyToManyField(Topping)

    def __str__(self):              # __unicode__ on Python 2
        return "%s (%s)" % (self.name, ", ".join(topping.name
                                                 for topping in self.toppings.all()))

现在我只想要素食菜单的元素,用西红柿过滤

pizza_item = Pizza.objects.filter(toppings__name='tomatoes')

我的选择是:

SELECT `pizza`.`id`, `pizza`.`name` 
FROM `pizza` 
INNER JOIN `pizza_toppings` ON ( 
    `pizza`.`id` = `pizza_toppings`.`pizza_id` ) 
INNER JOIN `web_topping` ON ( 
    `pizza_toppings`.`topping_id` = `topping`.`id` )
WHERE `topping`.`name` = azucar

但我想得到:

SELECT `pizza`.`id`, `pizza`.`name`, `topping`.`name` 
FROM `pizza` 
INNER JOIN `pizza_toppings` ON (
    `pizza`.`id` = `pizza_toppings`.`pizza_id` ) 
INNER JOIN `web_topping` ON ( 
    `pizza_toppings`.`topping_id` = `topping`.`id` ) 
WHERE `topping`.`name` = azucar

最后一个查询在 mysql db 中运行良好。并且使用 Pizza.objects.raw 但我想使用 django ORM 是topping.name 的选择,我尝试使用prefetch_select('toppings')。但我无法获得相同的选择。

【问题讨论】:

【参考方案1】:

您是否尝试过对 Queryset 使用 values 方法?

类似:

pizza_item = Pizza.objects.filter(toppings__name='tomatoes').values("id", "name", "toppings__name")

【讨论】:

您能详细描述一下您的解决方案吗? 这工作正常但不返回查询集,只返回值。但是sql代码是完美的。 Pizza_item = ['toppings__name': u'tomatoes', 'id': 1L, 'name': u'pizztomato']【参考方案2】:

我不确定这是否可行。因为当您使用 Pizza.objects... 时,您仅限于 Pizza 模型中的字段。由于 Pizza 模型不包含浇头的名称字段。您无法检索它。您只能检索 toppings 的 id 字段:

pizza_item = Pizza.objects.filter(toppings__name='tomatoes').values('id', 'name', 'toppings')

这将在 SELECT 中提供“toppings”。“topping_id”。

另外,既然你已经指定了 toppings__name='tomatoes,那么在这个查询集中所有的 toppings 的名字都会是西红柿,那么有 topping.@987654323 有什么意义呢? @ 在你的结果中?

【讨论】:

如果我使用 toppings__name= 不是问题,但如果我尝试使用 toppings__icontains='to' 我想获取所有查询。并希望使用查询集和“聚合” topping.name 来获取查询集。如果我使用 valuesqueryset 需要将所有内容添加到查询中,并且将来无法轻松更改模型。但是谢谢你的帮助!! 好的,我明白你的意思了。您必须使用 prefetch_related 从其他模型中获取值。 Pizza.objects.whatever() 不会得到另一个模型的名称字段。

以上是关于使用 django ORM 进行高级选择的主要内容,如果未能解决你的问题,请参考以下文章

Django的orm的高级操作

如何编写高级 Django ORM 查询

django model 高级进阶

Django之ORM

使用 python 在 Django 中进行高级搜索

占位先