• 10 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 28/11/2023

Validez les données

Ne permettez pas la création de tout et n’importe quoi

Attaquons-nous à présent à un autre sujet : la création d’entités et plus précisément de catégories, dans notre cas.

Notre endpoint actuel permet la lecture seulement, car il est destiné aux visiteurs de notre boutique. Nous allons très vite en mettre un second en place, qui sera dédié aux administrateurs qui, eux, auront la possibilité de créer, modifier et supprimer des données.

La création d’entité impose d’effectuer certains contrôles qui sont généralement de deux types :

  • Les contrôles sur un champ, comme par exemple vérifier que le nom d’une catégorie n'existe pas déjà, et ainsi éviter les doublons.

  • Les contrôles multichamps, comme la vérification que les deux mots de passe saisis à l’inscription sont les mêmes.

DRF nous permet de réaliser ces deux types de contrôles au travers de la réécriture de méthodes sur le serializer :

  • validate_XXX  où XXX est le nom du champ à valider ;

  • validate  qui permet un contrôle global sur tous les champs du serializer.

N’attendons pas plus longtemps pour mettre en place l'endpoint et les contrôles qui l’accompagnent. ;)

Validez les données d’un champ

Commençons tout de suite par la mise en place du nouvel endpoint sur l’URLhttp://127.0.0.1:8000/api/admin/category/  qui, comme son nom l’indique, servira à administrer les catégories.

Pourquoi ne pas utiliser l’endpoint déjà existant ?

Dans les endpoints d’administration :

  • Des serializers différents sont utilisés et les données retournées diffèrent ;

  • Certains accès peuvent également être limités à certaines personnes authentifiées. 

Dans le cadre de notre boutique, nous avons décidé de définir nos endpoints en fonction des acteurs qui les utilisent.

Créons notre nouvel endpoint d’administration qui cette fois-ci étend ModelViewset  et non plus ReadOnlyViewset. Celui-ci ne doit pas avoir de limitation sur les catégories actives, car il s’agit d’un endpoint d’administration.

class AdminCategoryViewset(MultipleSerializerMixin, ModelViewSet):
 
    serializer_class = CategoryListSerializer
    detail_serializer_class = CategoryDetailSerializer
 
    def get_queryset(self):
        return Category.objects.all()

Puis définissons notre nouvel endpoint en le déclarant auprès de notre routeur.

router.register('admin/category', AdminCategoryViewset, basename='admin-category')

Vérifions que notre endpoint est bien fonctionnel sur l’URLhttp://127.0.0.1/api/admin/category/.

Notre nouvel endpoint s’affiche bien, avec l’action POST à nouveau permise
Notre Admin Category Viewset List marche bien

Attendez, tout en bas, un formulaire est apparu avec un bouton POST, c’est quoi ?

Maintenant que nous utilisons un Viewset, la création de catégorie est possible. C’est à la création que sert ce formulaire en nous permettant d'effectuer des actions POST. Les actions de mise à jour et de suppression sont disponibles sur les URL de détail des catégories.

Validons à présent nos données, sans oublier que la création d’un doublon de catégorie ne doit pas être permis. Il nous faut pour cela modifier notre serializer de liste, car c’est lui qui est utilisé pour l’action create  .

La validation d’un champ unique se fait en écrivant la méthode validate_XXX  où XXX  est le nom du champ. Dans notre cas, validate_name  :

class CategoryListSerializer(serializers.ModelSerializer):
 
    class Meta:
        model = Category
        fields = ['id', 'date_created', 'date_updated', 'name']
 
    def validate_name(self, value):
        # Nous vérifions que la catégorie existe
        if Category.objects.filter(name=value).exists():
        # En cas d'erreur, DRF nous met à disposition l'exception ValidationError
            raise serializers.ValidationError('Category already exists')
        return value

Si nous tentons à présent de créer une catégorie qui existe déjà, une réponse en 400 avec des données contenant la nature de l’erreur sont renvoyées.

Quand nous essayons d’ajouter une catégorie qui existe déjà, le champ Name devient rouge et affiche le message
Une erreur s’affiche quand nous essayons d’ajouter une catégorie déjà existante

La validation de champ unique permet d’effectuer plein de contrôles, tant qu’ils sont effectués sur ce champ précis. On pourrait imaginer un système de filtre de mots pour un forum, par exemple.

Mettez en place une validation multiple

Pour notre boutique, nous souhaitons optimiser le référencement et avoir un rappel du nom de la catégorie également présent dans la description. Nous pouvons effectuer automatiquement ce contrôle au travers d’une validation multiple.

La validation entre champs se fait au travers de la méthode validate. Vérifions que le nom est bien présent dans la description :

class CategoryListSerializer(serializers.ModelSerializer):
 
    class Meta:
        model = Category
        # Pensons à ajouter « description » à notre liste de champs
        fields = ['id', 'date_created', 'date_updated', 'name', 'description']
 
    def validate_name(self, value):
        if Category.objects.filter(name=value).exists():
            raise serializers.ValidationError('Category already exists')
        return value
 
    def validate(self, data):
        # Effectuons le contrôle sur la présence du nom dans la description
        if data['name'] not in data['description']:
        # Levons une ValidationError si ça n'est pas le cas
            raise serializers.ValidationError('Name must be in description')
        return data

Nous pouvons alors constater que notre validation fonctionne si le nom de la catégorie n’est pas présent dans sa description.

Tant que le nom de la catégorie est aussi présent dans la description, nous pouvons effectuer un POST
Tant que le nom de la catégorie est aussi présent dans la description, nous pouvons effectuer un POST

Dans le screencast ci-dessous, je vous montre comment j'ai mis en place la validation dans notre projet :

À vous de jouer

Mettons en place un endpoint d’administration des articles pour les administrateurs de la boutique. Certains contrôles doivent être effectués :

  • Le prix doit être supérieur à 1 €.

  • Le produit associé doit être actif.

Pour réaliser cela, vous pouvez partir de la branche P2C4_exercice. Elle contient déjà ce que nous venons de faire ensemble. Une solution est proposée sur la branche P2C4_solution.

En résumé

  • Utiliser un ModelViewset permet l’utilisation de l’ensemble des actions du CRUD.

  • La validation d’un champ se fait au travers de la méthode validate_XXX  du serializer.

  • La validation multichamp se fait au travers de la méthode validate  du serializer.

La validation des données lors de la création et/ou la modification est un facteur clé pour assurer la cohérence des données, n’hésitez pas à valider toutes les données importantes. Maintenant, voyons comment tester les API externes avec les mocks – suivez-moi au prochain chapitre !

Exemple de certificat de réussite
Exemple de certificat de réussite