【发布时间】:2015-12-23 08:51:16
【问题描述】:
所以我有一个预订系统。代理商(提交预订的个人和组织)只能在我们分配的类别中进行预订。许多代理可以分配到相同的类别。这是一个简单的多对多。以下是模型的外观:
class Category(models.Model):
pass
class Agent(models.Model):
categories = models.ManyToManyField('Category')
class Booking(models.Model):
agent = models.ForeignKey('Agent')
category = models.ForeignKey('Category')
因此,当预订进入时,我们会根据代理商可用的类别动态分配类别。代理通常不指定。
我可以选择 Booking.category 不在 Booking.agent.categories 中的 Bookings 吗?
我们刚刚注意到——由于一个愚蠢的管理员错误——允许一些代理向任何类别提交预订。它让我们在错误的地方进行了数千次预订。
我可以解决这个问题,但我只能通过嵌套查找来让它工作:
for agent in Agent.objects.all():
for booking in Booking.objects.filter(agent=agent):
if booking.category not in agent.categories.all():
# go through the automated allocation logic again
这可行,但速度非常慢。数据库和 Django 之间有很多数据飞来飞去。这也不是一次性的。我想定期审核新的预订,以确保它们在正确的位置。似乎不可能发生另一个管理问题,因此在检查代理数据库后,我想查询 不在其代理类别中的预订。
同样,嵌套查询不起作用,但随着我们的数据集增长到数百万(甚至更多),我想更有效地做到这一点..
我觉得应该可以通过F() 查找来做到这一点,如下所示:
from django.db.models import F
bad = Booking.objects.exclude(category__in=F('agent__categories'))
但这不起作用:TypeError: 'Col' object is not iterable
我也尝试过.exclude(category=F('agent__categories')),虽然它对那里的语法更满意,但它并不排除“正确”的预订。
在 M2M 上执行这种F() 查询的秘诀是什么?
在我设置a Github repo with these models(和一些数据)之后,帮助确定我的确切身份。请使用它们来编写查询。当前唯一的答案是我在“真实”数据上看到的问题。
git clone https://github.com/oliwarner/djangorelquerytest.git
cd djangorelquerytest
python3 -m venv venv
. ./venv/bin/activate
pip install ipython Django==1.9a1
./manage.py migrate
./manage.py shell
然后在 shell 中开火:
from django.db.models import F
from querytest.models import Category, Agent, Booking
Booking.objects.exclude(agent__categories=F('category'))
这是一个错误吗?有没有合适的方法来实现这一点?
【问题讨论】:
标签: django django-models django-queryset