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

时间:2016-12-19 21:50:57

标签: django django-models django-queryset normalization database-normalization

问题: 我遇到的问题是在选择模型中获得选项的价格。这是因为,根据其他选项也在同一购物车中,将使用不同的价格来生成总额。如果该选项的 effector_option 本身位于同一个购物车中,我需要帮助我获取选项的价格,否则请使用< strong>变化,仅设置选项字段。

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

一页上可以有多个部分。每个部分可以包含许多选项,稍后可由用户选择。选定的选项将放入购物车中,该购物车将用于生成总价。

变体模型中,字段选项只是告诉我变体属于哪个选项。然而, Varaition 模型中的 effector_option 字段将由购物车使用。

用户可以选择任意数量的选项,但是,根据用户选择的选项,其他选项可能会显示变体之前选择 effector_option 的价格。

购物车应用模型包含:

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是否包含在同一 Cart 中。如果是,则显示该价格,否则显示Variation.effector_option为空/未设置的变化内的价格。

我发现购物车中的每个选择都会调用超过26个查询。这个db模式是否需要更多规范化,或者它对于这个简单的项目是否足够好?

1 个答案:

答案 0 :(得分:3)

  

我发现在购物车中为每个选择调用超过26个查询。这个db模式是否需要更多规范化,或者它对于这个简单的项目是否足够好?

我会咬人,因为我相信这个解决方案就是软件工程。这里的问题不是规范化,也不是Django。它是如何选择组织问题的。我猜测你已经陷入了一些陷阱,我将在讨论这些陷阱。首先让我们从你自己的......开始直接得到一些定义。

  • 部分 - 一组选项
  • 选项 - 价格
  • 变体 - 尝试对影响其他选项的选项进行建模

现在我们有这个问题吗?我的部分Option选项可与其他Option选项一起使用,并影响价格!混沌!我们需要Variation为其互动提供元规则。更多查询!更多逻辑!也许...

陷阱1

  

让屏幕上显示的内容可以驱动您的数据模型

我在这里猜测,但使用单词SectionOption让我觉得你正在组织一个屏幕而不是数据库。更常见的是,企业的模型看起来如下......

  • Product - 我们销售的商品(namebase_priceoptionsoption_sets
  • OptionSet - 一组选项,作为一揽子交易!想想节省的费用!(namegroupoptionspriceoptionset_exclusionsoption_exclusions
  • Option - 点菜选项(namegroupprice
  • Purchase - 有人想要购买的内容(productoptionsoptionsets

现在你可能会说“我的部分怎么样了!”分段可以像挂起OptionSetOption group CharField类型的group一样简单。在模板中进行渲染时,您可以通过exclusions将选项/选项集合在一起。您可以使用Option阻止人们为OptionSets选择有冲突的Productprefetch_related。现在整个shebang可以在页面上填充,只需3个查询(正确使用Options),并且可以简单地将选定的OptionSets / Variation添加到一起以获得确定的价格

陷阱2

  

让你想要它的工作方式阻止它工作

现在,在您发布“这对我不起作用,我只是一片雪花!”(已经很久了)。我们经常发现,我们希望某些东西能够发挥作用的方式阻碍了它的运作。

旧的unix负责人曾经讨论过一致性,简单性和完整性的优点。共识是,即使不完整或一致,简单性也是最好的。您的原始解决方案希望使用复杂性来实现完整性。 这是一个陷阱!(感谢admiral ackbar)

e.g。这是我/我的客户的业务运作方式,因此它必须以这种方式工作

当我们寻找实现简单性的方法时,软件更便宜/更容易编写。有时这意味着要改变组织以符合软件的限制。

我可以想象对上述陈述

的反驳

选项1将为您提供选项2的10%折扣。您只有静态价格!

这可以在上面的模式中建模,其中总价格等于期权1的价格+ .9(期权2的价格)。在这种情况下,我们刚刚采用Options的概念并将其作为数据而不是行为。更简单。它更灵活。我的意思是你可以在价格上做一些复杂的3D体积计算,只是将结果渲染到你的产品架构中。还有更多问题需要考虑......

我不想手工完成所有这些配置!

自己编写一个从电子表格导入的Django管理命令。

如果_spec之间的价格或关系发生变化怎么办?

大多数产品/价格架构都包含Option_spec之类的_spec概念,可让您捕获即时点购买条款。在购买商品时,Purchase条记录与Option相关联。这样,OptionSet和{{1}}可以在不更改所有已连接的过去购买的情况下进行更改。

并且列表继续......

这里的要点是,如果你聪明开朗,你可以梦想的所有问题都有简单的解决方案。