xticks python django serialization django-rest-framework

python - xticks - Cuándo usar Serializer''s create() y ModelViewset''s create() perform_create()



plot title python (1)

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

  1. El método create() del serializador. Aquí esta la documentation

    class CommentSerializer(serializers.Serializer): def create(self, validated_data): return Comment.objects.create(**validated_data)

  2. El método create() ModelViewset. Documentation

    class AccountViewSet(viewsets.ModelViewSet): queryset = Account.objects.all() serializer_class = AccountSerializer permission_classes = [IsAccountAdminOrReadOnly]

  3. El método ModelViewset perform_create() . Documentation

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

Estos tres enfoques son importantes según el entorno de su aplicación.

Pero ¿CUÁNDO necesitamos usar cada función create() / perform_create() ??. Por otro lado, encontré alguna cuenta de que se llamaron a dos métodos de creación para una sola solicitud posterior: create() modelviewset y create() serializer.

Esperemos que alguien comparta algunos de sus conocimientos para explicar y esto seguramente será muy útil en mi proceso de desarrollo.


  1. Usaría create(self, validated_data) para agregar cualquier detalle adicional en el objeto antes de guardar los valores AND "prod" en cada campo del modelo al igual que **validated_data hace. En términos ideales, desea hacer esta forma de "pinchar" solo en UNA ubicación, por lo que el método de create en su CommentSerializer es el mejor lugar. Además de esto, es posible que también desee llamar a API externas para crear cuentas de usuario de su lado justo antes de guardar sus cuentas en su propia base de datos. Debe usar esta función de create junto con ModelViewSet . Siempre piense: "Vistas delgadas, 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 el padre de ModelViewSet . CreateModelMixin funciones principales de CreateModelMixin son estas:

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

Como puede ver, la función de create anterior se encarga de llamar a la validación en su serializador y 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 la salida de respuesta de manejo :). Esto funciona bastante bien en conjunción con create(self, validated_data) encuentra en el serializador (donde podría residir la lógica de su aplicación específica).

  1. Ahora puede preguntarse, ¿por qué tenemos una función distinta de perform_create(self, serializer) con solo una línea de código!?!? Bueno, la razón principal detrás de esto es permitir la personalización cuando se llama a la función 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 el create(self, request, *args, **kwargs) y eso simplemente derrota el propósito de tener mixins haciendo el trabajo pesado y aburrido.

¡Espero que esto ayude!