124 votes

Quand utiliser la fonction create() du Serializer et la fonction perform_create() du ModelViewset ?

Je souhaite clarifier la documentation de Django-rest-framework concernant la création d'un objet modèle. Jusqu'à présent, j'ai trouvé qu'il y avait 3 approches sur la façon de gérer de tels événements.

  1. La fonction create() méthode. Voici la méthode la documentation

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
  2. L'ensemble ModelView create() méthode. Documentation

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
  3. L'ensemble ModelView perform_create() méthode. Documentation

    class SnippetViewSet(viewsets.ModelViewSet):
    
        def perform_create(self, serializer):
            serializer.save(owner=self.request.user)

Ces trois approches sont importantes en fonction de l'environnement de votre application. Mais quand devons-nous utiliser chacune d'entre elles ? create() / perform_create() fonction ? D'autre part, j'ai trouvé quelques comptes où deux méthodes de création ont été appelées pour une seule demande d'affichage, la fonction ModelViewSet 's create() et du sérialiseur create() .

159voto

Apoorv Kansal Points 1332
  1. Vous utiliserez create(self, validated_data) pour ajouter des détails supplémentaires dans l'objet avant de l'enregistrer ET des valeurs "prod" dans chaque champ du modèle, tout comme **validated_data fait. Dans l'idéal, il est préférable d'effectuer cette forme de "sondage" en UN SEUL endroit afin que les create dans votre CommentSerializer est le meilleur endroit. En outre, vous pouvez également appeler des API externes pour créer des comptes d'utilisateurs de leur côté, juste avant d'enregistrer vos comptes dans votre propre base de données. Vous devriez utiliser cette create en liaison avec la fonction ModelViewSet . Pensez toujours - "Thin views, Thick serializers" (vues minces, sérialiseurs épais).

    Exemple :

    def create(self, validated_data):
        email = validated_data.get("email", None)
        validated.pop("email") 
        # Now you have a clean valid email string 
        # You might want to call an external API or modify another table
        # (eg. keep track of number of accounts registered.) or even
        # make changes to the email format.
    
        # Once you are done, create the instance with the validated data
        return models.YourModel.objects.create(email=email, **validated_data)
  2. Les create(self, request, *args, **kwargs) dans la fonction ModelViewSet est défini dans le CreateModelMixin qui est le parent de ModelViewSet . CreateModelMixin Les principales fonctions de l'outil sont les suivantes :

    from rest_framework import status
    from rest_framework.response import Response
    
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    
    def perform_create(self, serializer):
        serializer.save()

    Comme vous pouvez le constater, les create se charge d'appeler la validation de votre sérialiseur et de produire la bonne réponse. La beauté de la chose, c'est que vous pouvez maintenant isoler votre logique d'application et NE PAS vous préoccuper des appels de validation banals et répétitifs et de la gestion de la réponse :). Cela fonctionne très bien en conjonction avec la fonction create(self, validated_data) trouvé dans le sérialiseur (où votre logique d'application spécifique pourrait résider).

  3. Vous vous demandez peut-être pourquoi nous avons un système d'information distinct. perform_create(self, serializer) avec une seule ligne de code !?!? Eh bien, la raison principale derrière cela est de permettre la personnalisation lors de l'appel de la fonction save fonction. Vous pouvez souhaiter fournir des données supplémentaires avant d'appeler save (comme serializer.save(owner=self.request.user) et si nous n'avions pas perform_create(self, serializer) vous devez remplacer la fonction create(self, request, *args, **kwargs) et cela va à l'encontre de l'objectif d'avoir des mixins qui font le travail lourd et ennuyeux.

0 votes

Bonjour, merci de partager vos connaissances ! A propos de la create(self, validated_data) dans le sérialiseur, cela signifie qu'il se concentre sur la logique de validation des données ? et surtout qu'il peut aider à renvoyer les données du sérialiseur dans la réponse, n'est-ce pas ?

1 votes

Non, à ce stade, vous avez déjà passé toutes vos validations. Je parle de la façon dont vous pourriez vouloir personnaliser les données validées juste avant qu'elles ne soient sauvegardées dans une base de données. Je donnerai un exemple dans ma réponse.

1 votes

Pas de problème, j'ai juste ajouté un exemple pour donner plus de contexte.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X