Django:检查对象是否存在于查询集中(IF ELSE)

6
我遇到的问题是在“选择”模型中获取选项价格。这是因为,根据同一购物车中还有哪些“选项”,将使用不同的价格生成总价。我需要一个查询集来获取“Option”的价格,如果该选项具有其自身位于同一购物车中的“影响器选项”,则使用该选项的价格,否则只使用选项字段设置的“变化”。
“TempName App”模型由以下内容组成:
class Section(models.Model):
    title = models.CharField(max_length=20)
    description = models.CharField(max_length=100)
    temp = models.ForeignKey(TempName, null=False)
    def __str__(self):
        return self.title
    def get_options(self):
        return self.option_set.all()

class Option(models.Model):
    name = models.CharField(max_length=120)
    section = models.ForeignKey(Section, null=False)
    def __str__(self):
        return self.name
    def get_variations(self):
        return self.variation_set.all()

class Variation(models.Model):
    name = models.CharField(max_length=60, blank=True, unique=True)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    option = models.ForeignKey(Option, null=False)
    effector_option = models.ForeignKey(Option, null=True, blank=True, related_name='option_effected')
    def __str__(self):
        return self.name

一页上可以有许多部分。每个部分都可以包含许多选项,用户稍后可以选择这些选项。所选选项将放入购物车中,用于生成总价。
Variation模型中,字段选项只告诉我Variation属于哪个选项。但是,在Variation模型中,effector_option字段将由购物车使用。
用户将被允许选择任意数量的选项。然而,根据用户选择的选项,其他选项可能会显示以前选择了effector_optionVariation价格。 Cart App模型包括:
class Cart(models.Model):
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
    creation_date = models.DateTimeField(verbose_name='creation date')
    checked_out = models.BooleanField(default=False, verbose_name='checked out')
    class Meta:
        verbose_name = 'cart'
        verbose_name_plural = 'carts'
        ordering = ('-creation_date',)
    def __str__(self):
        return unicode(self.creation_date)
    def get_selections(self):
        return self.selection_set.all()


class Selection(models.Model):
    cart = models.ForeignKey(Cart)
    option = models.ForeignKey(Option)
    @property
    def price(self):
        return 10

购物车可以包含用户选择的多个“选项”。每个“选择”都有一个价格属性,可以根据购物车中还有哪些其他“选项”,来向用户展示该个别“选项”的价格。
我尝试过:获取所有“选项”的变体。然后循环遍历每个变体,并检查“Variation.effector_option”是否包含在同一“购物车”中。如果是,则显示该价格;否则,显示“Variation.effector_option”为 null/未设置的变体中的价格。
我发现,每个“选择”在购物车中调用了超过 26 次查询。这个数据库模式需要更多的规范化吗?还是对于这个简单的项目已经足够了?

阅读有关如何查询(查询集运算符)而不是循环的内容。 - philipxy
@philipxy 是的,我已经做过了。然而,我遇到的问题是查询一个queryset,然后查询该结果queryset。我会再仔细阅读文档中的这一部分,也许我漏掉了什么。 - Erion S
1
谷歌搜索“stackoverflow.com django查询其他查询的结果”。 - philipxy
1个回答

5
我发现购物车中的每个选择会触发超过26个查询。这个数据库模式需要更多的规范化,或者对于这个简单的项目来说已经足够了吗? 我相信解决这个问题的方法是软件工程。这里的问题不在于规范化,也不在于Django。它在于你选择组织问题的方式。我猜测你已经陷入了一些陷阱,我们将在讨论中解释。首先,让我们明确一些定义,从你自己开始... “Section”-一组选项,“Option”-价格,“Variation”-试图模拟影响其他选项的选项的尝试。 现在我们有了这个问题,对吧?我的某些“Option”选择可以与其他“Option”选择一起使用并影响价格!混乱!我们需要“Variation”为它们的交互提供元规则。更多查询!更多逻辑!也许… 陷阱1 让屏幕上的外观驱动数据模型。我猜想你正在组织一个屏幕而不是一个数据库,因为“Section”和“Option”的用法让我感觉如此。更常见的做法是像以下这样的模型...
现在你可能会问:“我的部分怎么办!” Sections 可以简单地使用一个 CharField 类型,在 OptionSet 和 Option 上挂载的 metadata,名为 group 来实现。在模板中渲染时,您可以通过 group 将选项/选项集合并在一起。您可以使用 exclusions 来阻止人们选择与产品冲突的 Option 和 OptionSets。现在,只需使用至少 3 个查询(正确使用 prefetch_related)即可将整个功能放入页面,所选 Options/OptionSets 可以简单相加以获得确定性价格。 陷阱 2 让您想要的方式阻止其根本无法运行
在您发射“这对我来说不起作用,我是个例外!”之前(已经在这里待了很久)。我们经常发现,我们希望某些东西工作的方式成为它无法工作的障碍。
古老的 Unix 头脑曾就一致性、简洁性和完整性争论过长达数年。共识是即使不完整或一致,简单性也是最好的。您原始的解决方案似乎使用复杂性来实现完整性。这是一个陷阱!(感谢阿克巴上将)
例如,“这是我的/我的客户业务的方式,所以它必须按照这种方式工作。”
寻找实现简单性的方法可以使软件更便宜/更容易编写。有时,这意味着将组织更改为符合软件的限制。
我可以想象对上述内容的反驳是: 选项 1 将为选项 2 提供 10% 的折扣。你只有静态价格! 在上面的模式中,可以对其进行建模,其中总价等于 Option 1 的价格 + .9(Option 2 的价格)。在这种情况下,我们只是将 Variation 的概念变成了数据,而不是行为。更简单。它也更加灵活。我的意思是,您可以对价格进行一些复杂的三维容积计算,并将结果渲染到产品架构中。还有更多问题需要考虑...... 我不想手动执行所有这些配置! 编写一个 Django 管理命令,从电子表格中导入。 如果价格或 Options 之间的关系发生变化怎么办? 大多数产品/价格模式都包括一个名为 _spec 的概念,例如 Option_spec,它允许您捕获购买条款的时点。在购买物品时,_spec 记录与Purchase 相连接。这使得OptionOptionSet 可以更改,而不必更改所有已连接的过去购买记录。
等等...
重要的是,如果您聪明并开放思维,所有您能想到的问题都有简单的解决方案。

非常感谢你提供如此全面的答案。我会仔细研究你指出的每一个"陷阱"。 - Erion S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接