I have a model with a self-referential ManyToManyField:
class Release(models.Model):
# ...
bundled_releases = models.ManyToManyField("self", blank=True)
def get_bundles(self):
return Release.objects.filter(bundled_releases__in=[self.id])
I want get_bundles
to only return releases that have self
in their bundled_releases
fields, but this way it also returns releases in self
's bundled_releases
field. How do I do this?
Edit: and vice versa I need an alternative to release.bundled_releases.all
that returns the release's bundled_releases
but doesn't return releases that include the release in their own bundled_releases
.
Your relation is symmetrical, that is the problem. By default relations to itself have symmetrical=True
[Django-doc]. So that means that my_a.bundled_releases.all()
is the same as my_a.release_set.all()
.
You thus work with:
class Release(models.Model):
# …
bundled_releases = models.ManyToManyField(
'self', symmetrical=False, related_name='bundles', blank=True
)
There is no need to make a .get_bundles(…)
method however. Django makes relations accessible in two directions. Here you can trigger the relation in reverse with:
my_release.bundles.all()
This because of the related_name='bundles'
.