Semnale Django

  • 2 minute de citit

Disponibil și în English

Pe această pagină

De ceva vreme lucrez la un site web. La început l-am făcut cu Django + șabloane, iar acum folosesc Django Rest Framework și Angular.
Site-ul trebuie să fie o platformă pentru încărcarea lucrărilor științifice și pentru a oferi posibilitatea de a le evalua prin recenzie inter pares.

Ce vreau să discut în acest scurt articol este cum am simplificat dezvoltarea folosind semnalele Django pentru anumite cazuri de utilizare.

Documentația oficială descrie semnalele astfel:

Django include un „dispecer de semnale” care ajută aplicațiile decuplate să fie notificate atunci când au loc acțiuni în alte părți ale framework-ului. Pe scurt, semnalele permit unor expeditori să notifice un set de destinatari că a avut loc o anumită acțiune. Sunt deosebit de utile atunci când multe bucăți de cod pot fi interesate de aceleași evenimente.

În site-ul meu a trebuit să folosesc semnale în următoarele situații:

  • Crearea unui profil pentru fiecare utilizator.
  • Actualizarea modelului atunci când ceva s-a schimbat.

Crearea unui profil pentru fiecare utilizator.

Am deja definit un model de profil, să-l ignorăm.

[code language=”python”]
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_profile(sender, instance, created, **kwargs):
“””
Asigură că fiecare utilizator nou primește un profil.
“””
if created:
Profile.objects.create(user=instance)
[/code]

Acesta este semnalul care creează un profil nou pentru fiecare utilizator creat. Destul de simplu, nu? Nici nu mă voi obosi să explic codul.
La început suprascriam funcția create dintr-un serializer personalizat, dar asta funcționa doar când cream utilizatori prin apeluri API. Nu funcționa când administratorul crea utilizatori noi. Suprascrierea metodei save a modelului era greoaie și am evitat-o.

Actualizarea modelului atunci când ceva s-a schimbat.

Iată codul pentru celelalte două semnale:

[code language=”python”]
@receiver(pre_save, sender=Paper)
def editor_field_changed(sender, instance, **kwargs):
“””
Dacă există un editor și statusul lucrării este processing. Schimbă statusul în under_review.
Dacă nu există un editor și statusul lucrării este under_review, schimbă statusul în 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]

În esență, ce face acesta este să seteze statusul lucrării la under_review atunci când i se atribuie un editor și statusul actual al lucrării este processing.
Observați că semnalul este transmis la evenimentul pre_save de către modelul Paper.

[code language=”python”]
@receiver(post_save, sender=Review)
def reviews_changed(sender, instance, **kwargs):
“””
Dacă există o recenzie a editorului, setează statusul lucrării în funcție de rezultatul recenziei editorului.
“””
if instance.editor_review:
# Dacă recenzia editorului este pozitivă, schimbă statusul lucrării în 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]

Acest semnal este transmis la post_save de către modelul Review. Setează statusul lucrării la accepted sau preliminary_reject. Instanța de recenzie are un obiect paper, deci modelele sunt legate între ele.

Vă mulțumesc, sper că v-a fost de ajutor!
Dacă aveți întrebări, nu ezitați să comentați mai jos sau să mă contactați pe twitter.

Resurse