Cuándo usar create () de Serializer y create () perform_create () de ModelViewset

Quiero aclarar la documentación dada de django-rest-framework respecto a la creación de un objeto modelo. Hasta ahora he encontrado que hay tres enfoques sobre cómo manejar tales eventos.

  1. El método create() del serializador. Aquí está la documentación.

     class CommentSerializer(serializers.Serializer): def create(self, validated_data): return Comment.objects.create(**validated_data) 
  2. El método ModelViewset create() . Documentación

     class AccountViewSet(viewsets.ModelViewSet): queryset = Account.objects.all() serializer_class = AccountSerializer permission_classes = [IsAccountAdminOrReadOnly] 
  3. El método ModelViewset perform_create() . Documentación

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

Este enfoque de tres es importante dependiendo de su entorno de aplicación.

Pero ¿CUÁNDO necesitamos usar cada función create() / perform_create() ? Por otra parte, encontré que algunos métodos de creación fueron llamados para una sola solicitud de publicación. El create() modelviewset y el create() serializador.

Espero que alguien pueda compartir algo de su conocimiento para explicar y esto seguramente será muy útil en mi proceso de desarrollo.

  1. Debería usar create(self, validated_data) para agregar cualquier detalle adicional en el objeto antes de guardar Y “prod” valores en cada campo del modelo como lo hace **validated_data . Hablando de manera ideal, quiere hacer esta forma de “pinchar” solo en UNA ubicación para que el método de create en su CommentSerializer sea ​​el mejor. Además de esto, es posible que también desee llamar a apis externas para crear cuentas de usuario de su lado justo antes de guardar sus cuentas en su propia base de datos. Debe utilizar esta función de create junto con ModelViewSet . Siempre piensa – “Vistas finas, serializadores gruesos”.

Ejemplo:

 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 función create(self, request, *args, **kwargs) en ModelViewSet se define en la clase CreateModelMixin , que es la principal de ModelViewSet . CreateModelMixin principales funciones de CreateModelMixin son estas:

     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() 

Como puede ver, la función de create anterior se encarga de llamar a la validación de su serializador y de producir la respuesta correcta. La belleza detrás de esto, es que ahora puede aislar la lógica de su aplicación y NO preocuparse por las llamadas de validación mundanas y repetitivas y el manejo de la respuesta de respuesta :). Esto funciona bastante bien junto con la create(self, validated_data) encuentra en el serializador (donde podría residir la lógica de la aplicación específica).

  1. Ahora puede preguntar, ¿por qué tenemos una función separada de perform_create(self, serializer) con una sola línea de código? Bueno, la razón principal detrás de esto es permitir la personalización al llamar a la función de save . Es posible que desee proporcionar datos adicionales antes de llamar a save (como serializer.save(owner=self.request.user) y si no perform_create(self, serializer) , tendría que anular la create(self, request, *args, **kwargs) y eso simplemente create(self, request, *args, **kwargs) el propósito de tener mixins haciendo el trabajo pesado y aburrido.

¡Espero que esto ayude!