Django doc的'披萨示例的延伸(通过打顶的比萨饼屏幕)

时间:2013-09-03 03:24:41

标签: django database-design django-models data-modeling

https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-many-relationships,Django团队在比萨饼和浇头的背景下描述了多对多的关系。我已经举了他们的例子,试图找到一个概念问题的解决方案,我正在建模我自己的数据。

为了准确解释我因此Stack Overflow帖子而要完成的事情,请考虑以下(假设的)语法:

TOPPING = {'a'..'z' | 'A'..'Z'};
FLOAT = {'0'..'9'}, ['.', {'0'..'9'}]; (* Non-negative numbers only *)

QUERY = "Hey Django, find me all of the pizzas in the database such that:",
      { "(", (TOPPING), (">=" | "<=" | "=="), FLOAT, ") &&" },
      "(", (TOPPING, (">=" | "<=" | "=="), FLOAT, ")";

通过发出一些我想要观察的QUERY行返回的QuerySet。正如其内容所示,我希望Django向我返回一个QuerySet,其中所有的Pizza对象都符合我的筛选标准。我对models.py的外观或者实际的查询应该如何看起来没有信心。我只有足够的经验来解释上面的伪查询以及我希望返回的结果。

提前感谢您,我期待着您的建议。

额外信息

请注意,在我的特定情况下,在加载初始数据后,永远不会写入数据库。读取总是非常频繁。

我愿意使用原始SQL,但我更喜欢使用Django QuerySet API


在解决方案中尝试1:

我在模型中添加了一个ToppingAmount(models.Model)类。我给了它一个浮动的金额,以及两个外键将比萨饼和一个浇头相关联。

from django.db import models
class Topping(models.Model):
  name = models.CharField(max_length=128)

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

class Pizza(models.Model):
  name = models.CharField(max_length=128)
  toppings = models.ManyToManyField(Topping, through='ToppingAmount')

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

class ToppingAmount(models.Model):
  topping = models.ForeignKey(Topping)
  pizza = models.ForeignKey(Pizza)
  amount = models.FloatField()
  units = models.CharField(max_length=4) # e.g. 'g' | 'kg' | 'lb' | 'oz' ...

上述模型将允许其中一个(例如)执行ToppingAmount.objects.filter(topping__name='foo').filter(amount__gt=bar)并查找所有 ToppingAmount 对象,以使其披萨上至少有bar克foo。 / p>

不幸的是,它还允许不正常的ToppingAmount.objects.filter(pizza__name='pippo').filter(amount__gt=bar),它会找到所有 ToppingAmount 对象,这样在它的顶部至少有一些'pippo'条。

就我所能使用此模型和简单过滤器而言。我们无法针对其他浇头(或比萨;))和金额过滤生成的QuerySet,因为此QuerySet仅包含 ToppingAmount 对象。此QuerySet中的每个ToppingAmount对象都具有相同的顶部或相同的披萨。他们的所有金额(无论是解释为描述顶部还是披萨)都符合filter(amount...)

此外,我发现在这里使用多对多关系没有任何实际好处。消除Pizza类中的配料,同时保持其他所有内容相同,从而导致数据库具有相同的json转储和可能的查询相同的实用程序。


尝试2:

创建一个披萨表,其中包含所有146种可能配料的列。

from django.db import models
class Topping(models.Model):
  name= modles.CharField(max_length=128)
  units = models.CharField(max_length=4) # e.g. 'g' | 'kg' | 'lb' | 'oz' ...

class Pizza(models.Model):
    name = models.CharField(max_length=128)
    topping1_amount = models.FloatField()
    .
    .
    .
    topping146_amount = models.FloatField()

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

我相信这个解决方案是谨慎的,因为它创建了一个我认为不必要或不可取的大而稀疏的表(评论赞赏)。另一方面,为此模型编写查询非常简单:Pizza.objects.filter(topping1_amount__gt=20).filter(topping2_amount__lt=15)...

0 个答案:

没有答案