В REST-фреймворке Django, как мне вызвать метод validate моего сериализатора, а также проверить, что необходимые поля отправлены?
Я использую Python 3.9 с фреймворком Django REST (v 3.12.2). В представлении я проверяю, что поля объекта были представлены правильно, следующим образом...
@api_view(('POST',))
def save_to_sheet_from_form(request):
valid_ser = ValidateNewCoopSerializer(data=request.data)
if valid_ser.is_valid():
... do valid actions ...
return Response(post_data, status=status.HTTP_201_CREATED)
else:
return Response(valid_ser.errors, status=status.HTTP_400_BAD_REQUEST)
Мой сериализатор настроен следующим образом...
class ValidateNewCoopSerializer(serializers.Serializer):
# Set all fields as not required and allow_blank=true, so we can combine all validation into one step
id=serializers.CharField(required=False, allow_blank=True)
coop_name=serializers.CharField(required=False, allow_blank=True)
street=serializers.CharField(required=False, allow_blank=True)
address_public=serializers.CharField(required=False, allow_blank=True)
city=serializers.CharField(required=False, allow_blank=True)
state=serializers.CharField(required=False, allow_blank=True)
zip=serializers.CharField(required=False, allow_blank=True)
county=serializers.CharField(required=False, allow_blank=True)
country=serializers.CharField(required=False, allow_blank=True)
websites=serializers.CharField(required=False, allow_blank=True)
contact_name=serializers.CharField(required=False, allow_blank=True)
contact_name_public=serializers.CharField(required=False, allow_blank=True)
contact_email=serializers.CharField(required=False, allow_blank=True)
contact_email_public=serializers.CharField(required=False, allow_blank=True)
contact_phone=serializers.CharField(required=False, allow_blank=True)
contact_phone_public=serializers.CharField(required=False, allow_blank=True)
entity_types=serializers.CharField(required=False, allow_blank=True)
scope=serializers.CharField(required=False, allow_blank=True)
tags=serializers.CharField(required=False, allow_blank=True)
desc_english=serializers.CharField(required=False, allow_blank=True)
desc_other=serializers.CharField(required=False, allow_blank=True)
req_reason=serializers.CharField(required=False, allow_blank=True)
def validate(self, data):
"""
Validation of start and end date.
"""
errors = {}
# required fields
required_fields = ['coop_name', 'websites', 'contact_name', 'contact_name_public', 'entity_types', 'req_reason']
for field in required_fields:
if not data[field]:
errors[field] = 'This field is required.'
# contact info
contact_email = data['contact_email'] if 'contact_email' in data else None
contact_phone = data['contact_phone'] if 'contact_phone' in data else None
if not contact_email and not contact_phone:
errors['contact'] = 'Either contact phone or contact email is required.'
if errors:
raise serializers.ValidationError(errors)
return data
Проблема заключается в том, что мне пришлось добавить эти строки в мой метод validate ...
required_fields = ['coop_name', 'websites', 'contact_name', 'contact_name_public', 'entity_types', 'req_reason']
for field in required_fields:
if not data[field]:
errors[field] = 'This field is required.'
Мне кажется, что это немного небрежно, потому что я мог бы определить, что требуется в определении полей, например, так
coop_name=serializers.CharField()
Но если я это сделаю, то, похоже, метод "validate" сериализатора не будет вызван, и конкретно эта логика
contact_email = data['contact_email'] if 'contact_email' in data else None
contact_phone = data['contact_phone'] if 'contact_phone' in data else None
if not contact_email and not contact_phone:
errors['contact'] = 'Either contact phone or contact email is required.'
Есть ли способ определить обязательные поля, а также заставить вызвать метод validate моего сериализатора?
Я думаю, что при использовании serializers.Serializer вам придется явно определить required=True, если он требуется, иначе он всегда будет required=False по умолчанию.
coop_name = serializers.CharField() # Default required=False
Также попробуйте добавить
def validate(self, data):
validated_data = super().validate(data)
# Other validation here
...
return validated_data