How do you get the other side of a symmetrical self reference in a M2M django model?
Say we are making a parts catalog, and we have lots of Part
s and we want to have an Interchange
to show which parts can be used in place of another:
class Part(models.Model):
name = models.CharField(max_length=300)
number = models.CharField(max_length=200, default 'because numberphiles like more ids')
…
interchanges = models.ManyToManyField("self",
through='Interchange',
symmetrical=False,
# + sign per http://charlesleifer.com/blog/self-referencing-many-many-through/
# I have tried without the plus t omaintain the references as well, but can't seem to understand the difference(s)
related_name="interchanges_to+",
# through_fields per docs
through_fields=('reference', 'interchange')
)
# per this http://charlesleifer.com/blog/self-referencing-many-many-through/
def add_interchange(self, part, symm=True):
interchange = models.Interchange.objects.get_or_create(
reference_part=self,
interchange_part=part)
if symm:
# avoid recursion by passing `symm=False`
part.add_interchange(self, False)
return interchange
def remove_interchange(self, part, symm=True):
models.Interchange.objects.filter(
reference_part=self,
interchange_part=part).delete()
if symm:
# avoid recursion by passing `symm=False`
part.remove_interchange(self, False)
def get_interchanges(self):
return ", ".join([str(p) for p in self.interchanges.filter(interchange_part__reference=self)])
def get_references(self):
return …?
# This is where I don't know how to get the Parts that are referring to it as being an interchange
class Interchange(models.Model):
reference = models.ForeignKey(Part, related_name="reference_part")
interchange = models.ForeignKey(Part, related_name="interchange_part")
# just to confirm we have a M2M table, we will add a foregin key to a User if this interchange has been personally verified
confirmed_by = models.ForeignKey(User, null=True, blank=True)
# … others if needed
class Meta:
# because self-referencing, in this case, is silly, we make sure each part references another part
unique_together = ('reference', 'interchange')
in the Django admin, I have:
@admin.register(app.Part)
class PartAdmin(admin.ModelAdmin):
list_display = ['name',
'number',
# ▼ I can see the Parts itself Interchanges to
'get_interchanges',
# ▼ I can not see the Parts that reference itself as being an Interchange
'get_references']
Parts Model in admin for reference...
Here is what I am trying to get:
As a confirmation, the Interchange Model in admin:
How do you get the other side of symmetrical self-reference M2M django models?
How do I return Part
s that are in the interchange table but in the reference (first) column
Notes:
- using django 1.11
- I know that the symmetry being
False
is required when using a M2M through Model per the docs - This nice write-up helped me get quite far, but in the admin, I can't seem to get the
interchange_part
to show itsreference_part
s in the admin page (thusly I haven't even tried to see if it is possible in a view with different/particular function) - In the docs it states the second part of the tuple for
through_keys
is called thetarget
model, but I cant find out what to refer to the first one - I am sure that there is a way to go multiple levels deep, ie if part one interchanges to 2, and 2 => 3, then 1 should list 2 and 3 (but that isn't the focus at the moment)
- Please correct my misunderstandings, Thanks :)