I’ve been working on a website for some time now, at first I’ve made it with Django + templates and now I use Django Rest Framework and Angular.
The website is supposed to be a platform for uploading papers and offer the ability to peer review them.
What I want to talk about in this short article is how I simplified the development using Django signals for certain use cases.
The official docs describe signals as:
Django includes a “signal dispatcher” which helps allow decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events.
In my website I needed to use signals in the following situations:
- Create a profile for every user.
- Update model when something changed.
Create a profile for every user.
I have a profile model already defined, let’s ignore it.
def create_profile(sender, instance, created, **kwargs):
Ensure that every new user gets a profile.
That was the signal that creates a new profile for every user that is created, pretty easy, right? I will not even bother explaining the code.
At first I was overriding the create function from a custom serialiser, but that only worked when I was creating users via API calls, It didn’t work when the admin created new users, overriding save method of the model was cumbersome and I avoided it.
Update model when something changed.
Here’s the code for the other two signals:
def editor_field_changed(sender, instance, **kwargs):
If there’s an editor and paper status is processing. Change the status to under_review.
If there’s no editor and the paper status is under_review, change the status to processing.
if instance.editor and instance.status == Paper.STATUS_CHOICES:
instance.status = Paper.STATUS_CHOICES # under_review
elif instance.editor == None and instance.status == Paper.STATUS_CHOICES:
instance.status = Paper.STATUS_CHOICES # processing
Basically, what this does is to set the paper status to under_review when an editor is assigned to it and the paper’s current status is processing.
Notice that the signal is transmitted at the pre_save event by Paper model.
def reviews_changed(sender, instance, **kwargs):
If there’s an editor review, set the paper status according to the result of the editor review.
# If the editor review is positive, change the paper status to published.
if instance.appropriate == Review.APPROPRIATE_CHOICES \
and instance.recommendation == Review.RECOMMENDATION_CHOICES:
instance.paper.status = Paper.STATUS_CHOICES # accepted
instance.paper.status = Paper.STATUS_CHOICES # preliminary_reject
This signal is transmitted at post_save by the Review model, it sets the paper status to accepted or preliminary_reject. The review instance has a paper object so the models are tied together.
Thank you, I hope this helped you!
If you have any questions feel free to comment below or ask me on twitter.