DRF Serializer IntegerField Validation To Make Sure ForeignKey Does Exists
У меня есть ModelSerializer class, который использует IntegerField в качестве замены для ForeingKey отношения.
class CartItemCreateSerializer(serializers.ModelSerializer):
product_id = serializers.IntegerField()
class Meta:
model = CartItem
fields = ('id', 'product_id', 'quantity')
def validate_product_id(self, value):
if not Product.objects.filter(pk=value).exists():
raise serializers.ValidationError('Product not found')
return value
def save(self, **kwargs):
product_id = self.validated_data['product_id']
cart_id = self.context['cart_id']
product = Product.objects.get(id=product_id)
# product = get_object_or_404(Product, id=product_id)
cart_item, _ = CartItem.objects.get_or_create(
cart_id=cart_id, product=product)
cart_item.quantity += self.validated_data['quantity']
cart_item.save()
self.instance = cart_item
return self.instance
У меня два вопроса по поводу этого класса, первый касается кода, метод validate_product_id делает вызов к db, чтобы проверить, существует ли запрашиваемый объект Product, а затем внутри метода save происходит еще один вызов к db, чтобы получить тот же самый Product снова, я думаю, что этот способ не оптимизирован для запроса одного и того же объекта дважды. Есть ли лучший способ проверить существование или выдать соответствующую ошибку?
во-вторых, если я использую get_object_or_404, то количество кода для написания уменьшится, но нет возможности выдать краткое, но релевантное сообщение об ошибке, так что же вы обычно делаете?
Обычно используется специальный тип поля PrimaryKeyRelatedField.
Вам даже не нужно вручную объявлять его, так как это может быть сделано автоматически с помощью ModelSerializer.
class CartItemCreateSerializer(serializers.ModelSerializer):
class Meta:
model = CartItem
fields = ('id', 'product', 'quantity')
def save(self, **kwargs):
cart_id = self.context['cart_id']
product = self.validated_data['product']
cart_item, _ = CartItem.objects.get_or_create(
cart_id=cart_id, product=product)
cart_item.quantity += self.validated_data['quantity']
cart_item.save()
self.instance = cart_item
return self.instance
https://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield