0

I'd like to have automatic relation binding between two different m2m fields. Here is an example of my desired workflow:

  1. create a Tag "Green"
  2. create a Tag "Colors" and mark "Green" as a child
  3. now, when I go back to "Green" tag panel it needs to have "Colors" among parents

Unfortunately it's not that simple and I can't come up with anything. I tried setting symmetrical to True but it's just making unnecessary loop ("Green" is not a parent to "Colors"!)

# my models.py
class Tag(models.Model):
    ...
    children = models.ManyToManyField(
        'self',
        blank=True,
        related_name="kids",
        symmetrical=False
    )
    parents = models.ManyToManyField(
        'self',
        blank=True,
        related_name="folks",
        symmetrical=False
    )

Thanks for help.

gwaramadze
  • 4,523
  • 5
  • 30
  • 42
  • If you are referencing the django admin panel you might want to add a tag about that. It's not a M2M issue. – dmg Feb 20 '13 at 18:44
  • Thanks, so I did. But still no luck :/ – gwaramadze Feb 20 '13 at 22:49
  • Hmm, perhaps you should look into forms and way of creating custom forms (perhaps extending ModelForm). Anyway the two M2Ms are wrong. They represent the same thing. If you need this only for the admin panel, you can try and add a new model `Parentship` with 2 foreign keys to `Tag` and modify these relationships there. – dmg Feb 21 '13 at 10:32
  • Thanks, just noticed your latest comment. As suggested by Hamms, I scraped one m2m field as it was overcomplicated, indeed. Now I'm looking into admin panel representation. Thanks for advice, if I come up with final setup, I will edit my opening post. – gwaramadze Feb 21 '13 at 12:32

1 Answers1

2

I believe what you're trying to do can be accomplished with a single M2M relation. Check out the documentation for symmetrical. If you define one asymmetrical field, you can use the related_name argument to define the other relation:

class Tag(models.Model):
  name = models.TextField()
  children = models.ManyToManyField(
      'self',
      blank=True,
      related_name="parents",
      symmetrical=False
  )

green = Tag.objects.create(name='green')
color = Tag.objects.create(name='color')
color.children.add(green)
color in green.parents.all() # True
Hamms
  • 5,016
  • 21
  • 28
  • Thanks man, you saved the day! It really was that simple. Any idea how can I represent parents admin panel? Now I can see only children. – gwaramadze Feb 21 '13 at 12:26
  • I believe something [like this](http://stackoverflow.com/a/5625036/1810460) should work for you. – Hamms Feb 21 '13 at 18:46