NucuLabs.dev

Share this post

Django Signals

nuculabs.dev

Discover more from NucuLabs.dev

Programming, Cloud and Engineering! 👨‍🔬
Continue reading
Sign in

Django Signals

Denis Nuțiu
Jun 30, 2018
Share this post

Django Signals

nuculabs.dev
Share

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.

[code language="python"] @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_profile(sender, instance, created, **kwargs): """ Ensure that every new user gets a profile. """ if created: Profile.objects.create(user=instance) [/code]

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:

[code language="python"] @receiver(pre_save, sender=Paper) 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[0][0]: instance.status = Paper.STATUS_CHOICES[1][0] # under_review elif instance.editor == None and instance.status == Paper.STATUS_CHOICES[1][0]: instance.status = Paper.STATUS_CHOICES[0][0] # processing [/code]

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.

[code language="python"] @receiver(post_save, sender=Review) 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 instance.editor_review: # If the editor review is positive, change the paper status to published. if instance.appropriate == Review.APPROPRIATE_CHOICES[0][0] \ and instance.recommendation == Review.RECOMMENDATION_CHOICES[1][0]: instance.paper.status = Paper.STATUS_CHOICES[3][0] # accepted else: instance.paper.status = Paper.STATUS_CHOICES[2][0] # preliminary_reject instance.paper.save() [/code]

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.

Resources

  • https://docs.djangoproject.com/en/2.0/topics/signals/

  • https://docs.djangoproject.com/en/2.0/ref/signals/#

Share this post

Django Signals

nuculabs.dev
Share
Previous
Next
Comments
Top
New

No posts

Ready for more?

© 2023 NucuLabs.dev
Privacy ∙ Terms ∙ Collection notice
Start WritingGet the app
Substack is the home for great writing