web-dev-qa-db-fra.com

Quand utiliser Serializer create () et ModelViewset create () perform_create ()

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

  1. La méthode create() du sérialiseur. Voici le documentation

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. La méthode ModelViewset create(). Documentation

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

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

Ces trois approches sont importantes en fonction de votre environnement d'application.

Mais QUAND devons-nous utiliser chaque fonction create() / perform_create() ??. D'autre part, j'ai trouvé un compte qui indique que deux méthodes de création ont été appelées pour une demande de publication unique, à savoir create() de modelviewset et create() du sérialiseur.

Espérons que tout le monde partagera certaines de ses connaissances pour les expliquer, ce qui sera certainement très utile dans mon processus de développement.

62
Roel
  1. Vous utiliseriez create(self, validated_data) pour ajouter des détails supplémentaires à l'objet avant d'enregistrer des valeurs AND "prod" dans chaque champ de modèle, comme le fait **validated_data. Dans l’idéal, vous voulez utiliser cette forme de "repérage" dans un seul emplacement, de sorte que la méthode create dans votre CommentSerializer est le meilleur endroit. En plus de cela, vous pouvez également appeler des API externes pour créer des comptes utilisateur de leur côté juste avant de sauvegarder vos comptes dans votre propre base de données. Vous devriez utiliser cette fonction create en conjonction avec ModelViewSet. Pensez toujours - "Vues fines, 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 
    # 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)
  1. La fonction create(self, request, *args, **kwargs) dans ModelViewSet est définie dans la classe CreateModelMixin qui est le parent de ModelViewSet. Les fonctions principales de CreateModelMixin 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, la fonction create ci-dessus prend en charge l’appel de validation sur votre sérialiseur et la réponse correcte. La beauté derrière cela est que vous pouvez maintenant isoler la logique de votre application et ne PAS vous préoccuper des appels de validation banals et répétitifs et du traitement de la sortie de réponse :). Cela fonctionne assez bien avec le create(self, validated_data) trouvé dans le sérialiseur (où la logique de votre application spécifique pourrait résider).

  1. Maintenant, vous vous demandez peut-être pourquoi nous avons une fonction séparée 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. Vous voudrez peut-être 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 devrez remplacer le create(self, request, *args, **kwargs) et cela va à l'encontre du but de faire en sorte que mixins effectue le travail lourd et ennuyeux.

J'espère que cela t'aides!

82
Apoorv Kansal