Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Project in Django: Growing and validating with ...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Project in Django: Growing and validating with django signals

We begin with a giant form and need to create many objects from different models while discussing the first and basic approach to them arrive in Django Signals and the project can escalate and be maintainable

Avatar for Felipe Brigatto

Felipe Brigatto

May 25, 2019

Other Decks in Programming

Transcript

  1. whoarewe Felipe Brigatto System Information @ USP Software Developer @

    NIC.br Judge @ Pokémon TCG https://brigatto.dev Adilson Torres Computer Engineering @ USP Software Developer @ NIC.br @adilsontorres (Telegram) https://github.com/adilsontorres
  2. Context We got a lot of models The task says

    to create a giant form because automatizations Need to create models on cascade Also need to validate on cascade Need to be ATOMIC, easy rollbacks The user must know what’s the error
  3. SOLID + Stuff Single responsibility principle Open–closed principle Liskov substitution

    principle Interface segregation principle Dependency inversion principle Atomicity Scalability Maintainability Aging New developers
  4. def form_valid(self, form): try: with transaction.atomic(): attributes_for_noc = form.cleaned_data['attributes_for_noc'] attributes_for_adm

    = form.cleaned_data['attributes_for_adm'] attributes_for_com = form.cleaned_data['attributes_for_com'] attributes_for_mng = form.cleaned_data['attributes_for_mng'] if attributes_for_noc.has_correct_stuff: if attributes_for_noc.name.contains("Super"): noc = NOC.objects.create(attributes_for_noc) if attributes_for_adm.has_correct_stuff: if attributes_for_adm.name.contains("Super"): adm = ADM.objects.create(attributes_for_adm) if attributes_for_com.has_correct_stuff: if attributes_for_com.name.contains("Super"): com = COM.objects.create(attributes_for_com) if attributes_for_mng.has_correct_stuff: if attributes_for_mng.name.contains("Super"): mng = MNG.objects.create(attributes_for_mng) if not (noc and adm and com and mng): raise ValidationError("failed") messages.success(self.request, "created") return redirect(self.request.META.get('PATH_INFO')) except ValidationError as e: messages.error(self.request, e.messages) return redirect(self.request.META.get('PATH_INFO'))
  5. Giant form_valid() Sequential objects creation Can use with atomic for

    easy rollbacks Not so good for scalability: new forms, news methods, add through admin etc
  6. # MNG model def save(self, *args, **kwargs): if self.has_stuff_one_correct: if

    not self.stuff_two: raise ValidationError('Missing stuff two') else: if self._state.adding: self.stuff_three = self.foreign_model.attribute_one self.stuff_four = self.foreign_model.attribute_two self.stuff_five = self.foreign_model.attribute_three else: raise ValidationError('Stuff one is bad') self.full_clean() super().save(*args, **kwargs) # Similar code to COM, NOC and ADM models
  7. Overriding save() Encapsulate a bunch of database behavior that you’ll

    want to customize A classic use-case is if you want something to happen whenever you save an object It’s important to remember to call the superclass method super().save(*args, **kwargs) to ensure that the object still gets saved into the database Unfortunately, there isn’t a workaround when creating or updating objects in bulk, since none of save(), pre_save, and post_save are called. https://docs.djangoproject.com/en/2.2/topics/db/models/#overriding-model-methods
  8. clean() • Validations of the model • Validations of the

    fields ◦ block update fields def clean(self): self.block_update_fields('magical_id') self.validate_name_contains_magic() def validate_name_contains_magic(self): if not self.name.contains('magic') raise ValidationError('Not a magic name')
  9. Django Signals Management signals • pre_migrate • post_migrate Request/response signals

    • request_started • request_finished • got_request_exception Test signals • setting_changed • template_rendered Database Wrappers • connection_created Model signals • pre_init • post_init • pre_save • post_save • pre_delete • post_delete • m2m_changed • class_prepared https://docs.djangoproject.com/en/2.2/ref/signals/
  10. Django Signals (examples) # Do more stuff if object is

    new entry @receiver(post_save, sender=ModelCrazy) def create_crazy_stuff(sender, instance, **kwargs): if kwargs['created'] and not kwargs['raw']: if instance.super_crazy: create_crazy_stuff(instance) else: create_good_stuff(instance) # Update atributes if object is old entry @receiver(post_save, sender=ModelCrazy) def update_stuff(sender, instance, update_fields, **kwargs): if not kwargs['created'] and not kwargs['raw']: if instance and instance.can_update_stuff: instance.update_stuff()
  11. pre_save() • Fields validations or adjustments on the instance ◦

    field generator ◦ field processing (FileField, ImageField) @receiver(pre_save, sender=SomeModel) def format_fields(sender, instance, **kwargs): set_instance_field(instance)
  12. post_save() • Use of another model ◦ Creation of objects

    ◦ update fields @receiver(post_save, sender=SomeModel) def create_another_model(sender, instance, **kwargs): if kwargs['created'] and not kwargs['raw']: if instance.create_another_model: create_all_instance_of_model(instance) # Just make a curl whenever ModelNormal is saved @receiver(post_save, sender=ModelNormal) def call_method_to_stuff(sender, instance, **kwargs): curl_to_check_madness(instance)
  13. post_delete() • Deletes orphan instances of another model • Deletes

    a series of instances if necessary same model or another # Delete all children from ModelCrazy @receiver(post_delete, sender=ModelCrazy) def delete_orphan_from_crazy_always(sender, instance, **kwargs): delete_orphans(instance)
  14. pre_save() x save() x post_save() • Where validations are made

    • Field data adjustments • Arguments of each signal ◦ update_fields on pre_save ◦ created on post_save
  15. Dúvidas Where to find Felipe? https://brigatto.dev Where to find Adilson?

    https://github.com/adilsontorres @adilsontorres (Telegram)