Как передать запрос другому сериализатору для валидации
В моей базе данных есть две таблицы для вставки записи о товаре. Я храню информацию о продукте в таблице Product
, а остальную информацию, такую как Pirce, Quantity и т.д. храню в другой таблице ProductStock
.
Я планирую отправлять данные на сервер примерно следующим образом.
{
"name":'product name',
"branad":"socialcodia"
"product_stock":{
"price":"100",
"quantity":"50"
}
}
Я легко могу подтвердить информацию о продукте из ProductSerializer
. Но у меня нет никакой идеальной идеи для проверки данных ProductStockSerializer
.
ProductSerializer
from rest_framework import serializers
from .models import Product
from .models import Medical
class ProductSerializer(serializers.ModelSerializer):
medical = serializers.CharField(read_only=True)
id = serializers.CharField(read_only=True)
is_visible = serializers.CharField(read_only=True,default=True)
class Meta:
model = Product
fields = ['id','medical','category','item','brand','is_visible']
def validate(self, attrs):
request = self.context.get('request')
attrs['medical'] = Medical.objects.get(pk=request.info.get('medical'))
return attrs
Здесь я хочу также проверить информацию product_stock
, потому что она приходит с одним запросом. Есть ли способ импортировать ProductStockSerializer
в ProductSerializer
и передать данные этому сериализатору, а затем проверить их.
ProductStockSerializer
from rest_framework import serializers
from .models import ProductStock
from medical.models import Medical
class ProductStockSerializer(serializers.ModelSerializer):
medical = serializers.CharField(read_only=True)
class Meta:
model = ProductStock
fields = ['medical','distributer','product','variant','batch','purchase_price','price','quantity','location','low_stock','expire_date']
def validate(self, attrs):
attrs['medical'] = Medical.objects.get(self.context.get('request').info.get('medical'))
batch = attrs.get('batch')
purchase_price = attrs.get('purchase_price')
price = attrs.get('price'),
if len(batch) < 3 or len(batch) > 30:
raise serializers.ValidationError("Invalid Batch Number")
if type(purchase_price) != int or type(purchase_price) != float:
raise serializers.ValidationError("Invalid Purchase Price")
if type(price) != int or type(price) != float:
raise serializers.ValidationError("Invalid Price")
return attrs;
ProductViewSet
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def get_queryset(self):
if self.request.user.is_superuser:
return Product.objects.all()
return Product.objects.filter(medical=self.request.info['medical'])
Я буквально не представляю, как это сделать. Спасибо
Как насчет добавления данных ProductStockSerializer
в качестве поля в ProductSerializer
class ProductSerializer(serializers.ModelSerializer):
...
product_stock = ProductStockSerializer()
class Meta:
fields = [ ... , product_stock ]
Вы должны иметь возможность использовать product_stock в вашей валидации. Если вы планируете создавать ProductStock
объекты, используя этот вложенный сериализатор, пожалуйста, обязательно прочитайте о записываемых вложенных сериализаторах.
Ответ @coderiot абсолютно правильный.
Вот как я решил, но в нем гораздо больше кода, чем в приведенном выше ответе.
class ProductSerializer(serializers.ModelSerializer):
medical = serializers.CharField(read_only=True)
id = serializers.CharField(read_only=True)
is_visible = serializers.CharField(read_only=True,default=True)
stock = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Product
fields = ['stock','id','medical','category','item','brand','is_visible']
def get_stock(self,instance):
return ProductStockSerializer(instance=instance.stock,context=self.context).data
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['stock'] = ProductStockSerializer(context=self.context)
def validate(self, attrs):
request = self.context.get('request')
attrs['medical'] = Medical.objects.get(pk=request.info.get('medical'))
return attrs