I have a Django model that has two many-to-many relationships to the auth.User
class, like:
class Indicator(models.Model):
friends = models.ManyToManyField(User, related_name="+")
enemies = models.ManyToManyField(User, related_name="+")
The related_name is set to "+" so that there's no backwards relation , ie I don't need u.friends_set
and u.enemies_set
if u is a user.
Adding, removing, and clearing 'friends' and 'enemies' works fine - if I check directly in the database (ie not through Django) I can see the changes reflected as I would expect. However, if I get the query set through Django, I'm given the 'enemies' list whether I use i.friends.all()
or i.enemies.all()
(assuming i
is an Indicator instance).
If I examine the ManyRelatedManager, I see that the through
attribute is correct, which (if I understand correctly) is what allows add/remove/clear to work correctly:
>>> i.friends.through
<class 'project.app.models.Indicator_friends'>
However, the get_query_set
method basically gets the superclass (the User Manager) and calls filter on it with kwargs i.friends.core_filters
, which is {'+__pk': 404L}
(if the Indicator ID is 404). The core_filters are the same for both "friends" and "enemies", which explains why I incorrectly get the same query set for both.
I can work around this (without setting a related_name): instead of i.friends.all()
I can use:
[friend.user for friend in i.friends.through.objects.filter(indicator__id=i.id)]
However, that's hardly elegant.
(Django 1.3 - I haven't tried trunk, but from reading the code it appears to have the same behaviour, with Python 2.7).
Looking at django/db/models/fields/related.py, it appears that the related_name = '+' option is really tested with a last character string slice in ManyToOneRel.is_hidden(). So simply appending a '+' to any string should do the trick, allowing you to have unique names in a single model and still have the backwards relationships ignored.
you could always set your own query to the database directly. I believe the queryset does in fact think the indicator are the same. I am not sure how friends and enemies interact, but perhaps you can just query there specific id's instead.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.