Django modele, Podstawy_011:


Jak zaimplementować walidacje danych modeli Django?

Odpowiedź:

  • 1. Walidacje wynikające z definicji pól modeli:
  • 
    class A(models.Model):
        first_name = models.CharField(max_length=100)
        age = models.PositiveIntegerField()
    
    # W modelu A samą definicją pól narzucamy domyślne walidacje:
    #   first_name - max długość 100 znaków
    #   age - wymuszamy wartość dodatnią

  • 2. Customowe walidatory:
  • 
    def more_than18(value: int) -> bool:
      if value > 18:
           return True
      return False
    
    class B(models.Model):
        first_name = models.CharField(max_length=100)
        age = models.PositiveIntegerField(validators=[more_than_18])
    
    # W modelu B użyliśmy customowego walidatora 'more_than_18' na polu 'age'.
    

  • 3. Domyślny mechanizm walidacyjny na poziomie całego obiektu:
  • # Istnieje domyślny mechanizm sprawdzania danych na poziomie całego obiektu modelu, żeby go użyć należy zaimplementować metodę clean w modelu.
    # Poniżej przykład dla modelu C:
    
    class C(models.Model):
        first_name = models.CharField(max_length=100)
        age = models.PositiveIntegerField(validators=[more_than_18])
    
        def clean(data:) -> bool:
            IMPLEMENT logic
    

  • 4. Walidacja przy użyciu clean_FIELDNAME:
  • # Django pozwala na definiowanie metod walidacji dla poszczególnych pól modelu za pomocą metody clean_FIELDNAME.
    # Jest to bardziej granularne podejście niż implementowanie metody clean.
    
    class D(models.Model):
        first_name = models.CharField(max_length=100)
        age = models.PositiveIntegerField()
    
        def clean_age(self):
            if self.age < 18:
                raise ValidationError("Age must be at least 18.")
    
    # Tutaj clean_age zostanie wywołane podczas walidacji tego pola, np. w momencie wywołania metody full_clean na instancji modelu.
    
    

  • 5. Użycie Meta.constraints dla walidacji na poziomie bazy danych.
  • # Od Django 2.2 można definiować walidacje przy pomocy atrybutu constraints w klasie Meta.
    # Pozwala to na deklaratywne narzucanie ograniczeń, które są wymuszane także na poziomie bazy danych.
    
    from django.db.models import Q, CheckConstraint
    
    class E(models.Model):
        first_name = models.CharField(max_length=100)
        age = models.PositiveIntegerField()
    
        class Meta:
            constraints = [
                CheckConstraint(check=Q(age__gte=18), name='age_gte_18'),
            ]
    
    # Ten mechanizm jest użyteczny w przypadku prostych reguł, takich jak wymaganie, aby wartość była większa lub równa pewnej liczbie.
    


  • 6. Walidacja w metodzie save
  • 7. Walidacja na poziomie menedżera (Managera)


  • 8. Walidacja w metodach full_clean:
  • # Możesz ręcznie wywołać metodę 'full_clean' przed zapisaniem obiektu.
    # Ta metoda uruchamia wszystkie poziomy walidacji (pola, metody clean_FIELDNAME oraz clean).
    
    obj = G(first_name="John", age=15)
    obj.full_clean()  # Podniesie ValidationError, jeśli warunki nie są spełnione
    obj.save()
    
    # Metoda 'full_clean' nie jest automatycznie wywoływana przy zapisie w bazie.
    # Można, natomiast wprowadzić konwencję, aby ją ręcznie wywoływać w określonych miejscach kodu.
    

  • 9. Używanie walidatorów wbudowanych w Django:
  • # Przykład walidatora korzystającego z wyrażeń regularnych:
    
    from django.core.validators import RegexValidator
    
    class H(models.Model):
        phone_number = models.CharField(
            max_length=15,
            validators=[
                RegexValidator(
                    regex=r'^\+?1?\d{9,15}$',
                    message="Phone number must be entered in the format: '+999999999'."
                )
            ]
        )
    
    class PhoneNumber(models.Model):
        phone_number = models.CharField(
            max_length=15,
            validators=[RegexValidator(regex=r'^\+?1?\d{9,15}$')])
    


  • Podsumowując, metody walidacji w Django można stosować na wielu poziomach: od indywidualnych pól, przez walidację całych obiektów, aż po bardziej zaawansowane podejście z użyciem constraintów bazy danych lub menedżerów. Wybór odpowiedniej metody zależy od przypadku użycia i potrzeb projektu.