Django DatabaseError:SQL变量太多(筛选查询)

时间:2013-09-10 08:00:08

标签: sql django django-queryset

我正在尝试设计Extentions of the Django docs' pizza example (screen for pizzas by topping)的解决方案,并且一直在使用Attempt 1

到目前为止,我的解决方案仅适用于Django barfs之前的两个或三个筛选条件,并抛出 DatabaseError:太多的SQL变量 。我目前的理解是,这是由数据库限制引起的(在本例中为sqlite3)。我也有这样的印象:这个错误是代码不良与数据库配置不足的标志。但是我对SQL或QuerySet机制知之甚少,不知道程序员可以采取什么行动来避免这个错误。

我现在有以下问题:

1。 Django中的SQL变量是什么?

2。这些SQL变量如何在Django中累积?

3。这些SQL变量如何在Django中“刷新”?

4。我在下面的查询代码部分做了什么/不做什么,以至于会抛出这个错误?

models.py

from django.db import models

class Topping(models.Model):
  name = models.CharField(max_length=128, primary_key=True)
  units = models.CharField(max_length=4) # e.g. 'g' | 'kg' | 'lb' | 'oz' ...

  # On Python 3: def __str__(self):
  def __unicode__(self):
    return self.name

class ToppingAmount(models.Model):
  pizzaID = models.CharField(max_length=128)
  topping = models.ForeignKey(Topping)
  amount = models.FloatField()

  # On Python 3: def __str__(self):
  def __unicode__(self):
    return self.topping.name

class Pizza(models.Model):
  name = models.CharField(max_length=128, primary_key=True)
  toppings = models.ManyToManyField(ToppingAmount)

  # On Python 3: def __str__(self):
  def __unicode__(self):
    return self.name

查询代码

def screen_query(lte, gte):
  topping_amounts = ToppingAmount.objects.all()

  for c in lte:
    bad = topping_amounts.filter(topping__pk=c[0]).filter(amount__gt=c[1])
    for b in bad:
      topping_amounts = topping_amounts.exclude(pizzaID=b.pizzaID)

  for c in gte:
    topping_amountsg = ToppingAmount.objects.none()
    prima_good = topping_amounts.filter(topping__name=c[0]).filter(amount__gte=c[1])
    for g in prima_good:
      topping_amountsg = topping_amountsg | topping_amounts.filter(pizzaID=g.pizzaID)
    topping_amounts = topping_amountsg

  pizzas = Pizza.objects.none()
  for ta in topping_amounts:
    pizzas = pizzas | Pizza.objects.filter(pk=ta.pizzaID)

  return pizzas

代码说明:

约束的形式为“amount”,> = | < =“,”value“并放在gte或lte列表中。例如,以下列表表明我们将筛选所有Pizza对象的数据库,使得它们具有:

  1. 不超过30.0的“Pepperoni”
  2. 不超过63.813的“Pineapple”
  3. 至少10.0个“Bell Peppers”
  4. 至少55个“Ham”
  5. 至少10.0的“培根”
  6. 至少55个“鸡”
  7. lte = [["Pepperoni", 30.0], ["Pineapple", 63.813]]
    gte = [["Bell Peppers", 10.0], ["Ham", 55], ["Bacon", 10.0], ["Chicken", 55]]
    

    我们通过将所有比萨(通过ToppingAmount)视为候选人来开始我们的查询:

    topping_amounts = ToppingAmount.objects.all()  
    

    接下来,在违反“金额”,< =“,”value“约束(通过topping_amounts)的情况下识别并排除所有比萨饼:

    for c in lte:
      bad = topping_amounts.filter(topping__pk=c[0]).filter(amount__gt=c[1])
      for b in bad:
        topping_amounts = topping_amounts.exclude(pizzaID=b.pizzaID)
    

    现在我们已经确定了所有符合lte规定的约束的topping_amounts对象,我们可以选择那些符合我们gte约束的对象。这是通过创建一个空的QuerySet topping_amountsg = ToppingAmount.objects.none()并用允许的对象填充它来完成的。

    for c in gte:
      topping_amountsg = ToppingAmount.objects.none()
      prima_good = topping_amounts.filter(topping__name=c[0]).filter(amount__gte=c[1])
    

    我们表面可行的ToppingAmount对象现在位于prima_good。回想一下,披萨有很多浇头,所以我们必须收集与每个初步可行披萨相关的所有ToppingAmount对象。

      for g in prima_good:
        topping_amountsg = topping_amountsg | topping_amounts.filter(pizzaID=g.pizzaID)
    

    topping_amounts QuerySet设置为等于pirma facie可行的ToppingAmount对象,并针对gte中的下一个约束进行过滤。

      topping_amounts = topping_amountsg
    

    gte上造成所有topping_amounts约束后,我们将拥有可行的QuerySet。

    Extentions of the Django docs' pizza example (screen for pizzas by topping)关注获取可行的Pizza对象的QuerySet,因此我们从topping_amounts中的可行ToppingAmount对象中提取它们。

    pizzas = Pizza.objects.none()
    for ta in topping_amounts:
      pizzas = pizzas | Pizza.objects.filter(pk=ta.pizzaID)
    

    将所有部分放在筛选查询功能中:

    def screen_query(lte, gte):
      topping_amounts = ToppingAmount.objects.all()
    
      for c in lte:
        bad = topping_amounts.filter(topping__pk=c[0]).filter(amount__gt=c[1])
        for b in bad:
          topping_amounts = topping_amounts.exclude(pizzaID=b.pizzaID)
    
      for c in gte:
        topping_amountsg = ToppingAmount.objects.none()
        prima_good = topping_amounts.filter(topping__name=c[0]).filter(amount__gte=c[1])
        for g in prima_good:
          topping_amountsg = topping_amountsg | topping_amounts.filter(pizzaID=g.pizzaID)
        topping_amounts = topping_amountsg
    
      pizzas = Pizza.objects.none()
      for ta in topping_amounts:
        pizzas = pizzas | Pizza.objects.filter(pk=ta.pizzaID)
    
      return pizzas
    

    如果您使用

    在shell中运行此代码
    lte = [["Pepperoni", 30.0], ["Pineapple", 63.813]]
    gte = [["Bell Peppers", 10.0], ["Ham", 55], ["Bacon", 10.0], ["Chicken", 55]]
    

    你会得到

    文件“/usr/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py”,第344行,执行     返回Database.Cursor.execute(self,query,params) DatabaseError:SQL变量太多

0 个答案:

没有答案