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.
-
El método
create()
del serializador. Aquí esta la documentationclass CommentSerializer(serializers.Serializer): def create(self, validated_data): return Comment.objects.create(**validated_data)
-
El método
create()
ModelViewset. Documentationclass AccountViewSet(viewsets.ModelViewSet): queryset = Account.objects.all() serializer_class = AccountSerializer permission_classes = [IsAccountAdminOrReadOnly]
-
El método ModelViewset
perform_create()
. Documentationclass 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.
-
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 decreate
en suCommentSerializer
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 decreate
junto conModelViewSet
. 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)
-
La función
create(self, request, *args, **kwargs)
enModelViewSet
se define en la claseCreateModelMixin
, que es el padre deModelViewSet
.CreateModelMixin
funciones principales deCreateModelMixin
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).
-
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ónsave
. Es posible que desee proporcionar datos adicionales antes de llamar asave
(comoserializer.save(owner=self.request.user)
y si noperform_create(self, serializer)
, tendría que anular elcreate(self, request, *args, **kwargs)
y eso simplemente derrota el propósito de tener mixins haciendo el trabajo pesado y aburrido.
¡Espero que esto ayude!