多个对象排除多对多

时间:2016-03-16 00:19:16

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

我有以下型号:

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()

我得到了#34;太多的值要打开" (虽然我觉得我应该注意到目前数据库中只有5个交易和2个客户)

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

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

我哪里错了?

3 个答案:

答案 0 :(得分:2)

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

这可以保存您在联接表中的字段排除。

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

答案 1 :(得分:0)

您想要更改此内容:

Twilio.Device.setup()

对于这样的事情:

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

基本上,deals = Deal.objects.exclude(customer__id__in=[1,2,etc..]).all() customer外键,因此您无法直接使用many-to-many

答案 2 :(得分:0)

已保存的交易和被解雇的交易是描述几乎相同的两个字段。如果允许这两个字段存储Null值,则在数据库中也可能存在太多列的风险。值得考虑删除dismissed_deals,并将saved_deal仅用于True或False语句。

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

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

真正的交易本来是由一个客户/买家而不是少数。真正的客户可以拥有数百万的交易,因此与客户达成交易将是一个好方法。

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

我想要做的是为客户检索交易,但我不想包含他们已经解雇的交易。

deals_saved = deals_for_customer.filter(saved = True)

客户和名称(customer__name)之间有双重下划线,它允许过滤model_name(客户与模型名称CustomerProfile相关)和该模型中的字段名称(假设CutomerProfile类具有名称属性)

{{1}}

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