How to automatically create a symmetric object on Django ManyToManyField?

I want to create a symmetrical relationship on my model, and also add a field to the relation. I met this blog (as well as this another blog ) and followed the steps to create my own models.

class CreditCardIssuer(models.Model): name = models.CharField(_('name'), max_length=256) transfer_limits = models.ManyToManyField('self', through='Balancetransfer', related_name='no_transfer_allowed+', symmetrical=False, help_text=_('List of issuers to which balance transfer is not allowed.')) def add_balancetransfer(self, creditcardissuer, until): balance_transfer, _newly_created = Balancetransfer.objects.get_or_create( no_transfer_from=self, no_transfer_to=creditcardissuer, until=until) balance_transfer, _newly_created = Balancetransfer.objects.get_or_create( no_transfer_from=creditcardissuer, no_transfer_to=self, until=until) return balance_transfer def remove_balancetransfer(self, creditcardissuer, until): Balancetransfer.objects.filter( no_transfer_from=self, no_transfer_to=creditcardissuer, until=until).delete() Balancetransfer.objects.filter( no_transfer_from=self, no_transfer_to=creditcardissuer, until=until).delete() return def get_transfer_limits(self, until): return self.transfer_limits.filter( no_transfer_to__until=until, no_transfer_to__no_transfer_from=self) class Balancetransfer(models.Model): no_transfer_from = models.ForeignKey('CreditCardIssuer', related_name='no_transfer_from') no_transfer_to = models.ForeignKey('CreditCardIssuer', related_name='no_transfer_to') until = models.IntegerField(blank=True, null=True, help_text='Minimum card ownership period to allow balance transfer.') class Meta: unique_together = ('no_transfer_from', 'no_transfer_to') 

But when I create relations from the administrator, only one is created. Could you help me deal with the problem?

+6
source share
1 answer

You say that you have one half of this in the Django admin (you do not say how, but I will assume that it works if you do not publish the code): the remaining step is to establish half of the relationship that is missing.

I suspect that if you put a breakpoint in your add_balancetransfer() method ( import pdb; pdb.set_trace() ), you will find that it is never called - part of the created relationship is executed through the Django built-in administrator behavior.

In short, you may need to just call add_balancetransfer() yourself when the model is saved, or, even better, another version that adds the missing relation.

One way to do this is to override the save() model method , but it can be a little fragile. For your situation, it might be better to fill in the missing link in the post_save signal model :

 from django.db.models.signals import post_save from django.dispatch import receiver from yourapp.models import CreditCardIssuer @receiver(post_save, sender=CreditCardIssuer) def add_missing_relationship(sender, **kwargs): # Add the other side of what should be a symmetrical relationship ... 
+1
source

Source: https://habr.com/ru/post/922010/


All Articles