1

I have a few recursive Django ManytoManyField's that use the 'through attribute' in my app. here is an example:

class Author(models.Model):
    user = models.OneToOneField(User, parent_link=True)
    introduction = models.TextField(blank=True)
    pictures = models.ManyToManyField('Graphic', related_name='users', null=True)
    organizations = models.ManyToManyField('Organization', related_name='members')
    expertise = models.ManyToManyField('Tag', related_name='experts', null=True)
    interests = models.ManyToManyField('Tag', related_name='interested_in', null=True)
    saved_articles = models.ManyToManyField(Article, related_name='favorited_by', null=True, through='SavedArticles')
    authors_followed = models.ManyToManyField('self', related_name='authors_followed', null=True, through='FollowedAuthors', symmetrical=False)

class FollowedAuthors(models.Model):
    author = models.ForeignKey(Author)
    trustee = models.ForeignKey(Author)
    notes = models.TextField()
    tags = models.ManyToManyField('Tag')

I know I could access MyAuthor.authors_followed.all(), but if I wanted call FollowedAuthor.authors_followed.all() to return MyAuthor, couldn't I just use related_name='authors_followed'? Does that just negate the symmetrical=False behavior?

A similar question was asked here, but in that case they had:

recursive_field = models.ManyToManyField('self', through='ThroughTable', related_name='different_field').

Am I missing some understanding of how symmetrical and related_name work?

Community
  • 1
  • 1
Eric H.
  • 6,894
  • 8
  • 43
  • 62

1 Answers1

2

If I understand correctly, I think you should have something like:

authors_followed = models.ManytoManyField('self', related_name='following_authors', null=True, through='FollowedAuthors', symmetrical=False)

That way,

MyAuthor.following_authors.all()

will return the authors that are following MyAuthor, and

MyAuthor.author_followed.all()

will return the authors that MyAuthor is following.

With your configuration, Django is not able to make the difference and identify the direction you want.

Arthur
  • 1,974
  • 2
  • 21
  • 28
  • Thanks, yeah I understand that. But I want MyAuthor.authors_followed.all() to return both authors that MyAuthor follows and authors that follow MyAuthor indistinguishably - as a sort of mutual friendship. Is Django going to raise an error when I try to syncdb with the code I have? – Eric H. Mar 15 '12 at 18:00
  • oh, ok, I didn't get that. You could try "python manage.py validate" if you don't want to syncdb. I think it won't work the way you have it. (Actually, I _hope_ it won't work). Two options then: 1. you could drop the symmetrical=False, but I guess you put it here for a reason; 2. create a function, maybe a property, that would gather the whole family (following and followed authors). – Arthur Mar 15 '12 at 18:11
  • Ahhh ha. Yes I was kinda hoping it wouldn't work either and it didn't when I ran manage.py validate. Error states: Reverse query name 'authors_followed' clashes with m2m field Author.authors_followed. I'll have to write the function merging the querysets like you suggested. – Eric H. Mar 15 '12 at 18:47
  • Looks like django doesn't let you have your asymmetrical and not eat it too (consume it with 2 queries). Sorry for the triple-negative brain twister. – hobs Jun 16 '12 at 01:25