В 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
Вернуться на верх