I have a serializer in which I would like to give the opportunity to send a NEW address with a POST request OR give an ID of an already existing address. One of both is required, but right now it asks for both to be given.
Any possibility to achieve that it validates with a condition?
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
#fields = '__all__'
exclude = ['in_calculation','canceled',]
address = AdressSerializer()
addressid = serializers.CharField(source='address')
read_only_fields = ['id','user','status','costs','']
CodePudding user response:
You could use validate()
and a customized create
/update
method like this:
class OrderSerializer(serializers.ModelSerializer):
address_detail = AddressSerializer(write_only=True, required=False)
class Meta:
model = Order
fields = (
'address', # to set from an existing address
'address_detail', # to create a whole new address
)
extra_kwargs = {
'address': {'required': False}, # make `address` to optional if your address in model is required.
}
def validate(self, attrs):
# if `address` and `address_detail` are both present or none of them is present
if bool('address' in attrs) == bool('address_detail' in attrs):
raise serializers.ValidationError('You can specify exactly one from these two fields.')
return attrs
def create(self, validated_data):
# do custom logic
CodePudding user response:
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
extra_kwargs = {
'address': {'required': False},
}
exclude = [] # some fields that should not be shown
read_only_fields = [] # some fields that should not be edited
# Add a nested Serializer to add new addresses while creating an order
address_detail = addressSerializer(required=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
try:
if "GET" in self.context['request'].method:
self.fields['client'] = ClientSerializer()
# ... some Nested Serializers which are ready-only on GET request.
except KeyError:
pass
def create(self,validated_data):
# check for uniqueness of ordernr and clientnr
try:
order = Order.objects.get(client=validated_data.get('client'),ordernr=validated_data.get('ordernr'))
if order:
raise ValidationError({'ordernr':'Ordernumber and Client-combination already exists'})
except ObjectDoesNotExist:
if validated_data.get('address_detail'):
address_detail = validated_data.pop('address_detail')
if address_detail:
address, existent = address.objects.get_or_create(**address_detail)
order = Order.objects.create(**validated_data, address=address)
elif validated_data.get('address'):
order = Order.objects.create(**validated_data)
return order
def validate(self, data):
validationerrors = {}
print(data)
# if `address` and `address_detail` are both present or none of them is present
if bool('address' in data) == bool('address_detail' in data):
validationerrors['address'] = "You need to specify exactly one from these two fields."
# a lot of other validations...
if validationerrors:
raise serializers.ValidationError(validationerrors)
return data