【问题标题】:Django: Checking if object exists in queryset (IF ELSE)Django:检查查询集中是否存在对象(IF ELSE)
【发布时间】:2016-12-19 21:50:56
【问题描述】:

我遇到的问题是在 Selection 模型中获取选项的价格。这是因为,根据同一购物车中还有哪些其他选项,将使用不同的价格来生成总价。我需要一个查询集的帮助,它可以让我得到 Option 的价格,如果该选项有一个 effector_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

一页上可以有多个部分。每个Section 可以包含许多Options,用户稍后可以选择这些Options。选定的选项将进入购物车,用于生成总价。

Variation 模型中,字段选项只是告诉我 Variation 属于哪个选项。 Varaition 模型中的 effector_option 字段将被购物车使用。

用户可以选择任意数量的选项,但是,根据用户选择的选项,其他选项可能会显示变化 strong> 之前选择 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

购物车可以包含用户选择的多个选项。每个 Selection 都有一个 price 属性,可用于根据同一购物车中的其他 Option 向用户显示单个选择的价格。

我的尝试:

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

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

【问题讨论】:

  • 了解如何查询(查询集运算符)而不是循环。
  • @philipxy 是的,我已经做到了,但是我遇到的问题是查询查询集,然后查询生成的查询集。我将再次阅读文档的那部分,也许我错过了一些东西。
  • Google 'stackoverflow.com django 其他查询的查询结果'。

标签: django django-models django-queryset


【解决方案1】:

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

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

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

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

陷阱1

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

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

  • Product - 我们卖的东西(name, base_price, options, option_sets)
  • OptionSet - 组合成一揽子交易的选项组!想想省钱吧!(namegroupoptionspriceoptionset_exclusionsoption_exclusions
  • Option - 点菜选项(namegroupprice
  • Purchase - 有人想买什么(productoptionsoptionsets

现在您可能会说“我的部分呢!”部分可以像在 OptionSetOption 上挂起一段元数据一样简单,称为 groupCharField 类型。在模板中渲染时,您可以通过group 将选项/选项集组合在一起。您可以使用exclusions 来阻止人们为Product 选择冲突的OptionOptionSets。现在,整个 shebang 只需 3 个查询(正确使用 prefetch_related)就可以在页面上弹出,并且选择的 Options/OptionSets 可以简单地加在一起以获得确定的价格。

陷阱 2

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

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

旧的 unix 头脑曾经争论过一致性、简单性和完整性的优点。共识是简单性是最好的,即使它不完整或不一致。您的原始解决方案看起来使用复杂性来实现完整性。 这是一个陷阱!(感谢阿克巴上将)

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

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

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

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

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

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

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

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

大多数产品/价格架构都包含 _spec 的概念,例如 Option_spec,它允许您捕获时间点购买条款。 _spec 记录在购买时连接到 Purchase。这允许OptionOptionSet 在不更改所有已连接的过去购买的情况下进行更改。

名单还在继续……

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

【讨论】:

  • 感谢您提供非常全面的回答。我会调查你指出的每一个“陷阱”。
猜你喜欢
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 2021-01-05
  • 1970-01-01
  • 2018-03-04
  • 2017-12-26
  • 2017-10-28
  • 1970-01-01
相关资源
最近更新 更多