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

Eri*_*n V 6 django normalization django-models django-queryset database-normalization

问题: 我遇到的问题是在选择模型中获得选项的价格.这是因为,根据哪些其他选项也在同一购物车中,将使用不同的价格来生成总数.我需要一个查询集的帮助,它可以获得Option的价格,如果该选项有一个effector_option,它本身在同一个购物车中,使用它,否则使用Variation只有选项字段集.

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
Run Code Online (Sandbox Code Playgroud)

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

Variation模型中,field选项只是告诉我Variation属于哪个选项.然而,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
Run Code Online (Sandbox Code Playgroud)

购物车可以包含用户选择的多个选项.每个选择都有一个价格属性,可用于向用户显示该个别选择的价格,具体取决于哪个其他选项也在同一购物车中.

我做了什么:

获取选项的所有变体.然后遍历每个变体并检查Variation.effector_option是否包含在同一个Cart中.如果是,则显示该价格,否则显示Variation.effector_option为空/未设置的变体内的价格.

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

nsf*_*n55 5

我发现购物车中的每个选择都调用了超过 26 个查询。这个数据库模式是否需要更多的规范化,还是对于这个简单的项目来说已经足够好了?

我会咬一口,因为我相信解决这个问题的方法是软件工程。这里的问题不是规范化,也不是 Django。它是您选择组织问题的方式。我猜你已经落入了一些陷阱,我将在我们进行时讨论。首先,让我们从您自己的定义开始直接获得一些定义......

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

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

陷阱 1

让事物在屏幕上的显示方式驱动您的数据模型

我猜在这里,但使用的话Section,并Option让我觉得像你正在组织一个屏幕,而不是一个数据库。更常见的企业具有如下所示的模型......

  • Product- 我们卖的东西( name, base_price, options, option_sets)
  • OptionSet- 作为一揽子交易组合在一起的选项组!想想节省!( name, group, options, price, optionset_exclusions, option_exclusions)
  • Option-点菜选项( name, group, price)
  • Purchase- 有人想买什么 ( product, options, optionsets)

现在您可能会说“我的部分呢!” 部分可能就像挂起一块元数据OptionSet并用类型Option调用一样简单。在模板中渲染时,您可以将选项/选项集分组在一起。您可以使用从选择冲突的阻止人们和为。现在,整个 shebang 只需 3 次查询(正确使用)即可在页面上弹出,并且可以简单地将选定的/加在一起以获得确定性价格。groupCharFieldgroupexclusionsOptionOptionSetsProductprefetch_relatedOptionsOptionSets

陷阱 2

让你希望它工作的方式阻止它工作

现在,在你发起“这对我不起作用,我是雪花!”(在这里很长时间)之前。我们经常发现,我们想要的东西工作的方式阻碍了它的工作。

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

例如,这是我/我客户的业务运作方式,因此它必须以这种方式运作

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

我可以想象对上述陈述的反驳

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

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

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

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

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

大多数产品/价格模式都包含允许您捕获时间点购买条款的_spec相似概念。记录与购买时的记录相关联。这允许并在不更改所有连接的过去购买的情况下进行更改。Option_spec_specPurchaseOptionOptionSet

而这样的例子不胜枚举...

这里的重点是,如果你聪明且思想开放,你能想到的所有问题都有简单的解决方案。