In Django I do have two models "Author" and "Publication" that are connected with a Many-to-Many-Field, so that I can assign different authors to a publication. Additionally, I have to use a custom through-model "Authorship" to define the correct order.
class Author(models.Model):
first_name = models.CharField(max_length=48)
.....
class Authorship(models.Model):
author = models.ForeignKey(Author)
publication = models.ForeignKey('Publication')
order_of_authorship = models.IntegerField(default=1)
class Publication(models.Model):
title = models.CharField(max_length=128)
authors = models.ManyToManyField(Author, through=Authorship)
year = models.IntegerField(max_length=4)
...
citation_key = models.CharField(max_length=9, blank=True, default="")
At the moment I use the Admin Interface to populate my data with a form for the "Publication" and an inline form "Authorship".
What I want to achieve now: An additional citation_key-field (e.g. "Einstein1950") should be auto-populated after data has changed.
What I tried to do: I found out that using signals must be the best practice.
However the "m2m_changed"-Signal on "Publication.authors.through" is not fired, when I change the Authorships.
@receiver(m2m_changed, sender=Publication.authors.through)
def authors_changed(sender, **kwargs):
print("authors changed")
This problem is also discussed in a related topic, where the author seems to use "post_save" on the through-model.
@receiver(post_save, sender=Authorship)
def authorship_changed(sender, instance, **kwargs):
print("authors changed")
This seems to work out, but I have to keep in mind, that a deletion is not covered yet, so I added a post_delete-signal:
@receiver(post_delete, sender=Authorship)
def authorship_deleted(sender, instance, **kwargs):
print("authors deleted")
The problem now is: If I add 4 authors, I get that event fired 4 times. If I want to update my citation_key as described before, this happens also 4 times.
Can this be the correct solution? Or is there a better best practice? I assume it must work somehow with the m2m_changed signal, but I don't know how. Since I am new to Django, I don't know if this is the obvious solution for you. Furthermore, in this scenario the unnecessary calculation should not have a huge impact, but it is not nice at all.
I only found a really old bug-report in the Django-Trac that seems to address this problem as well. But there is not solution yet.
This is a known bug, reported as ticket 17688 on Django.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With