我有一个Q& A应用程序,允许用户阻止/隐藏他们觉得烦人或冒犯的其他用户。当current_user查看所有问题时 - Question.objects.all() - 我想从查询集中排除被current_user阻止的用户提出的所有问题 - Block.objects.filter(user_is_blocking = current_user)
最有效的方法是什么?如果它对您的答案产生影响,我会将相同的排除列表应用于其他模型,例如Answers,其中还包括User作为FK。
型号:
class Question(models.Model):
user = models.ForeignKey(User)
question = models.CharField()
class Block(models.Model):
user_is_blocking = models.ForeignKey(User, related_name="user_blocking")
user_is_blocked = models.ForeignKey(User, related_name="user_blocked")
更新: 由于sk1p,我得到了这个工作。然后我想要排除双向 - 所以我只看到我没有阻止的用户的问题和没有阻止我的人。对于那些对组合子查询感兴趣的人,我这样做了如下:
from itertools import chain
i_am_blocking = User.objects.filter(user_blocked__user_is_blocking=request.user)
is_blocking_me = User.objects.filter(user_blocking__user_is_blocked=request.user)
blocked_users = list(chain(i_am_blocking, is_blocking_me))
questions = Question.objects.exclude(user__in=blocked_users)
...
答案 0 :(得分:2)
您可以使用__in
字段查找:
class Question(models.Model):
user = models.ForeignKey(User)
question = models.CharField()
class Block(models.Model):
user_blocking = models.ForeignKey(User, related_name="blocks_set")
user_blocked = models.ForeignKey(User, related_name="blocks_received")
blocked_users = User.objects.filter(blocks_received__user_blocking=current_user)
questions = Question.objects.exclude(user__in=blocked_users)
(我冒昧地重命名你的相关名字和字段,以便更好地理解问题,你当然不必更改你的名字......)
__in
查找将被转换为子查询,因此数据库将完成大部分工作。
实际性能取决于您的数据库。关于MySQL的错误优化的Django文档warns,特别是,我建议对生产数据库的副本运行生成的查询,并查看EXPLAIN
或{的查询计划{1}}(在PostgreSQL上)。
如果基于子查询的方法与数据库不兼容,则可以将其重写为原始SQL查询并比较性能:
EXPLAIN ANALYZE
想法是将阻止表加入问题的作者,如果存在,则丢弃问题。 SELECT q.*
FROM app_question q,
auth_user author
LEFT JOIN app_block b ON (b.user_blocked_id = author.id)
LEFT JOIN auth_user ON (b.user_blocking_id = auth_user.id AND auth_user.id = %s)
WHERE author.id = q.user_id AND auth_user.id IS NULL;
是当前用户id的参数;一定要not use string formatting!