Oli*_*Oli 10 django django-models django-queryset
所以我有一个预订系统.代理商(提交预订的人员和组织)仅允许在我们分配的类别中进行预订.许多代理可以分配到相同的类别.这是一个简单的多对多.以下是模型的概念:
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')
Run Code Online (Sandbox Code Playgroud)
因此,当预订进入时,我们会根据代理商可用的类别动态分配类别.代理通常不指定.
我们刚刚注意到 - 由于一个愚蠢的管理员错误的优雅 - 一些代理人被允许提交任何类别的预订.它让我们在错误的地方有成千上万的预订.
我可以解决这个问题,但我只能通过嵌套查找来实现它:
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
Run Code Online (Sandbox Code Playgroud)
这可行,但它超级慢.这是数据库和Django之间的大量数据.这也不是一次性的.我想定期审核新的预订,以确保它们在正确的位置.在检查代理数据库之后,似乎不会发生另一个管理问题,我想查询不在其代理的类别中的预订.
同样,嵌套查询不会起作用,但随着我们的数据集增长到数百万(甚至更多)我想更有效地做到这一点.
我觉得应该可以通过F()
查找来执行此操作,如下所示:
from django.db.models import F
bad = Booking.objects.exclude(category__in=F('agent__categories'))
Run Code Online (Sandbox Code Playgroud)
但这不起作用: TypeError: 'Col' object is not iterable
我也尝试过.exclude(category=F('agent__categories'))
,虽然它的语法更快乐,但它并没有排除"正确"的预订.
F()
在M2M上进行此类查询的秘密公式是什么?
为了帮助确定我在使用这些模型(以及一些数据)设置Github仓库后的确切内容.请用它们来编写查询.当前唯一的答案点击和问题我也看到了我的"真实"数据.
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
Run Code Online (Sandbox Code Playgroud)
在壳中,火:
from django.db.models import F
from querytest.models import Category, Agent, Booking
Booking.objects.exclude(agent__categories=F('category'))
Run Code Online (Sandbox Code Playgroud)
那是一个错误吗?有没有正确的方法来实现这一目标?
我有可能错了,但我认为反过来应该这样做:
bad = Booking.objects.exclude(agent__categories=F('category'))
编辑
如果上面不起作用,这是另一个想法.我在设置上尝试了类似的逻辑,似乎有效.尝试添加中间模型ManyToManyField
:
class Category(models.Model):
pass
class Agent(models.Model):
categories = models.ManyToManyField('Category', through='AgentCategory')
class AgentCategory(models.Model):
agent = models.ForeignKey(Agent, related_name='agent_category_set')
category = models.ForeignKey(Category, related_name='agent_category_set')
class Booking(models.Model):
agent = models.ForeignKey('Agent')
category = models.ForeignKey('Category')
Run Code Online (Sandbox Code Playgroud)
然后你可以做一个查询:
bad = Booking.objects.exclude(agent_category_set__category=F('category'))
Run Code Online (Sandbox Code Playgroud)
当然,指定一个中间模型有它自己的含义,但我相信你可以处理它们.
归档时间: |
|
查看次数: |
1187 次 |
最近记录: |