与related_name为“+”的多个多对多关系会导致错误的查询集

时间:2011-11-03 03:43:57

标签: python django

我有一个Django模型,它与auth.User类有两个多对多关系,如:

class Indicator(models.Model):
    friends = models.ManyToManyField(User, related_name="+")
    enemies = models.ManyToManyField(User, related_name="+")

related_name设置为“+”so that there's no backwards relation,即如果您是用户,我不需要u.friends_setu.enemies_set

添加,删除和清除“朋友”和“敌人”的工作正常 - 如果我直接在数据库中检查(即不通过Django),我可以看到我所期望的反映。但是,如果我通过Django获取查询集,我会给出'敌人'列表,无论我使用i.friends.all()还是i.enemies.all()(假设i是一个指标实例)。

如果我检查了ManyRelatedManager,我发现through属性是正确的,如果我理解正确的话,那就是允许添加/删除/清除正常工作的内容:

>>> i.friends.through
<class 'project.app.models.Indicator_friends'>

但是,get_query_set方法basically获取超类(用户管理器)并使用kwargs i.friends.core_filters调用过滤器,{'+__pk': 404L}(如果指标ID)是404)。 core_filters对于“朋友”和“敌人”都是相同的,这解释了为什么我错误地为两者设置了相同的查询集。

我可以解决这个问题(不设置related_name):而不是i.friends.all()我可以使用:

[friend.user for friend in i.friends.through.objects.filter(indicator__id=i.id)]

然而,这并不优雅。

  1. 这是Django的“set related_name to'+'”系统的限制吗? (我无法在任何地方找到记录) - 即每个不同的对象/对象对只能使用'+'一次?
  2. 这是一个Django错误(即report的东西)?
  3. 有没有更好的方法来解决这个问题?
  4. (Django 1.3 - 我没有尝试过trunk,但是通过阅读代码它似乎具有相同的行为,使用Python 2.7)。

2 个答案:

答案 0 :(得分:1)

查看django / db / models / fields / related.py,看来related_name ='+'选项实际上是在ManyToOneRel.is_hidden()中使用最后一个字符串切片进行测试的。因此,只需在任何字符串中添加“+”就可以解决问题,允许您在单个模型中使用唯一的名称,并且仍然忽略向后关系。

答案 1 :(得分:-1)

您可以随时直接为数据库设置自己的查询。我相信查询集确实认为指标是相同的。我不确定朋友和敌人是如何互动的,但也许你只能在那里查询特定的id。