【问题标题】:Many to Many Exclude on Multiple Objects多对多排除多个对象
【发布时间】:2016-03-16 00:19:16
【问题描述】:

我有以下型号:

class Deal(models.Model):
    date = models.DateTimeField(auto_now_add=True)
    retailer = models.ForeignKey(Retailer, related_name='deals')
    description = models.CharField(max_length=255)
    ...etc

class CustomerProfile(models.Model):
    saved_deals = models.ManyToManyField(Deal, related_name='saved_by_customers', null=True, blank=True)
    dismissed_deals = models.ManyToManyField(Deal, related_name='dismissed_by_customers', null=True, blank=True)

我想做的是为客户检索交易,但我不想包含他们已取消的交易。

我无法理解多对多关系,并且无法弄清楚如何进行此查询。我假设我应该在 Deal.objects() 上使用排除,但我看到的所有排除示例都排除了一项,而不是多项。

当我天真地尝试时:

deals = Deal.objects.exclude(customer.saved_deals).all()

我收到错误:“'ManyRelatedManager' 对象不可迭代”

如果我说:

deals = Deal.objects.exclude(customer.saved_deals.all()).all()

我收到“太多值无法解包”(尽管我觉得我应该注意现在数据库中只有 5 个交易和 2 个客户)

我们(我们的客户)假设他/她将来会拥有成千上万的客户和数万笔交易,因此我希望尽我所能保持以绩效为导向。如果此设置不正确,我很想知道更好的方法。

另外,我正在运行 django 1.5,因为它部署在 App Engine 上(使用 CloudSQL)

我哪里错了?

【问题讨论】:

    标签: django google-app-engine django-models


    【解决方案1】:

    建议您使用 customer.saved_deals 获取要排除的交易 ID 列表(使用 values_list 快速转换为平面列表)。

    这应该可以帮助您排除连接表中的字段。

    deals = Deals.exclude( id__in=customer.saved_deals.values_list('id', flat=True) )
    

    【讨论】:

      【解决方案2】:

      你想改变这个:

      deals = Deal.objects.exclude(customer.saved_deals).all()
      

      这样的:

      deals = Deal.objects.exclude(customer__id__in=[1,2,etc..]).all()
      

      基本上,customermany-to-many 外键,所以不能直接与exclude 一起使用。

      【讨论】:

        【解决方案3】:

        已保存交易和已取消交易是描述几乎相同事物的两个字段。如果允许这两个字段存储 Null 值,也可能会在数据库中使用过多的列。值得考虑完全删除dismissed_deals,并仅将saved_deal 与True 或False 语句一起使用。

        要考虑的另一件事是将 saved_deals 从 CustomerProfile 类移到 Deals 类。 Saved_deals 是关于 Deals 的,因此它可以更喜欢住在 Deals 类中。

        class Deal(models.Model):
            saved = models.BooleandField()
            ...
        

        真正的交易将由一位客户/买家完成,而不是少数。一个真正的客户可能有数百万笔交易,因此将交易与客户关联起来是个好方法。

        class Deal(models.Model):
            saved = models.BooleanField()
            customer = models.ForeignKey(CustomerProfile)
            ....
        

        我想做的是为客户检索交易,但我不想包含他们已取消的交易。

        deals_for_customer = Deals.objects.all().filter(customer__name = "John")
        

        customer 和 name (customer__name) 之间有双下划线,可以过滤 model_name(customer 与 CustomerProfile 相关的模型名称)和该模型中的字段名称(假设 CutomerProfile 类具有 name 属性)

        deals_saved = deals_for_customer.filter(saved = True)
        

        就是这样。我希望我能帮上忙。如果没有,请告诉我。

        【讨论】:

          猜你喜欢
          • 2022-09-29
          • 1970-01-01
          • 1970-01-01
          • 2013-01-11
          • 2021-11-05
          • 2018-04-19
          • 2015-03-31
          • 1970-01-01
          • 2014-09-11
          相关资源
          最近更新 更多