Django Rest Framework Правильно ли я делаю?
Я сам изучал DRF и меня беспокоит один вопрос, к сожалению мне не кому его задать и этот вопрос беспокоит меня постоянно. Является ли хорошим подходом написание логики приложения в представлениях (как в приложенном коде)? При отправке запроса на сервер с намерением, например, принять заказ, мне приходится обновлять значения из других моделей, кроме заказа, или проводить валидацию статусов, изменять данные на их основе. В первых учебниках, из которых я узнал, среди прочих, JustDjango вся логика находится в представлении. Однако, после написания некоторого кода и просмотра других руководств, я чувствую, что это не правильный подход. Разве сохранение и обновление моделей не должно осуществляться через сериализатор? Если да, то через один большой сериализатор или несколько маленьких сериализаторов.
У вас так много логики в views.py, что это не лучший способ. Отделите действия модели от других представлений и сериализаторов. Например, для операций с заказами вы можете реализовать представление и сериализаторы следующим образом.
class UpdateOrderSerializer(serializers.ModelSerializer):
pzitem_id = serializers.CharField()
ordered_quantity = serializers.IntegerField()
user = serializers.PrimaryKeyRelatedField(User.objects.all())
item = serializers.PrimaryKeyRelatedField(OrderItem.objects.all())
class Meta:
model = Order
def validate(self, attrs):
attrs = super().validate(attrs)
if attrs["ordered_quantity"] < 0:
raise serializers.ValidationError(dict(ordered_quantity="Próbujesz zamówić ujemną wartość"))
def update(self, instance, validated_data):
instance.status = "WTZ"
# do some other things
instance.save()
return instance
class ZK_AddUpdateItemWithInstaReservation(ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = OrderSerializer
queryset = Order.objects.all()
@action(detail=True)
def update_order(self, request, pk):
serializer = self.get_serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(status=HTTP_200_OK, data={})
Если у вас много операций, которые связаны между собой. Вы можете создать конвейер. Например, так;
class YourPipeline:
def __init__(self, past_some_data):
self.past_some_data = past_some_data
def update_order_status(self):
# update your order
def create_order_item(self):
# do something else
def some_function(self):
# another operation
def run(self):
self.update_order_status()
self.create_order_item()
self.some_function()
return instance
class UpdateOrderSerializer(serializers.ModelSerializer):
pzitem_id = serializers.CharField()
ordered_quantity = serializers.IntegerField()
user = serializers.PrimaryKeyRelatedField(User.objects.all())
item = serializers.PrimaryKeyRelatedField(OrderItem.objects.all())
class Meta:
model = Order
def validate(self, attrs):
attrs = super().validate(attrs)
if attrs["ordered_quantity"] < 0:
raise serializers.ValidationError(dict(ordered_quantity="Próbujesz zamówić ujemną wartość"))
def update(self, instance, validated_data):
pipeline = YourPipeline(past_some_data=past_some_data)
return pipeline.run()
class ZK_AddUpdateItemWithInstaReservation(ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = OrderSerializer
queryset = Order.objects.all()
@action(detail=True)
def update_order(self, request, pk):
serializer = self.get_serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(status=HTTP_200_OK)
На мой взгляд, в вашем случае в коде есть несколько ошибок:
Как вы написали, сохранение данных должно осуществляться через сериализатор. На мой взгляд, это должен быть один сериализатор, который будет записывать данные в одной транзакции.
.В случае ошибок вы не должны возвращать код состояния 200, только одну из 4XX ошибок
Если вы хотите уменьшить или увеличить поле модели:
item.quantity_not_ordered -= int(ordered_quantity)
вам следует использовать https://docs.djangoproject.com/en/4.0/ref/models/expressions/#avoiding-race-conditions-using-f
- Вы не должны использовать
try:
foo()
except:
pass
Отличная практика заключается в явном перехвате всех исключений, которые могут возникнуть