tododrf序列化正确抛出异常,给前端

编程

class BaseSerializer(Field):

def is_valid(self, raise_exception=False):

assert not hasattr(self, "restore_object"), (

"Serializer `%s.%s` has old-style version 2 `.restore_object()` "

"that is no longer compatible with REST framework 3. "

"Use the new-style `.create()` and `.update()` methods instead." %

(self.__class__.__module__, self.__class__.__name__)

)

assert hasattr(self, "initial_data"), (

"Cannot call `.is_valid()` as no `data=` keyword argument was "

"passed when instantiating the serializer instance."

)

if not hasattr(self, "_validated_data"):

try:

self._validated_data = self.run_validation(self.initial_data)

except ValidationError as exc:

self._validated_data = {}

self._errors = exc.detail

else:

self._errors = {}

if self._errors and raise_exception:

raise ValidationError(self.errors)

return not bool(self._errors)

默认验证 to_internal_value

class Serializer(BaseSerializer, metaclass=SerializerMetaclass):

default_error_messages = {

"invalid": _("Invalid data. Expected a dictionary, but got {datatype}.")

}

@cached_property

def fields(self):

"""

A dictionary of {field_name: field_instance}.

"""

# `fields` is evaluated lazily. We do this to ensure that we don"t

# have issues importing modules that use ModelSerializers as fields,

# even if Django"s app-loading stage has not yet run.

fields = BindingDict(self)

for key, value in self.get_fields().items():

fields[key] = value

return fields

@property

def _writable_fields(self):

for field in self.fields.values():

if not field.read_only:

yield field

@property

def _readable_fields(self):

for field in self.fields.values():

if not field.write_only:

yield field

def get_fields(self):

"""

Returns a dictionary of {field_name: field_instance}.

"""

# Every new serializer is created with a clone of the field instances.

# This allows users to dynamically modify the fields on a serializer

# instance without affecting every other serializer instance.

return copy.deepcopy(self._declared_fields)

def get_validators(self):

"""

Returns a list of validator callables.

"""

# Used by the lazily-evaluated `validators` property.

meta = getattr(self, "Meta", None)

validators = getattr(meta, "validators", None)

return list(validators) if validators else []

def get_initial(self):

if hasattr(self, "initial_data"):

# initial_data may not be a valid type

if not isinstance(self.initial_data, Mapping):

return OrderedDict()

return OrderedDict([

(field_name, field.get_value(self.initial_data))

for field_name, field in self.fields.items()

if (field.get_value(self.initial_data) is not empty) and

not field.read_only

])

return OrderedDict([

(field.field_name, field.get_initial())

for field in self.fields.values()

if not field.read_only

])

def get_value(self, dictionary):

# We override the default field access in order to support

# nested HTML forms.

if html.is_html_input(dictionary):

return html.parse_html_dict(dictionary, prefix=self.field_name) or empty

return dictionary.get(self.field_name, empty)

def run_validation(self, data=empty):

"""

We override the default `run_validation`, because the validation

performed by validators and the `.validate()` method should

be coerced into an error dictionary with a "non_fields_error" key.

"""

(is_empty_value, data) = self.validate_empty_values(data)

if is_empty_value:

return data

value = self.to_internal_value(data)

try:

self.run_validators(value)

value = self.validate(value)

assert value is not None, ".validate() should return the validated data"

except (ValidationError, DjangoValidationError) as exc:

raise ValidationError(detail=as_serializer_error(exc))

return value

def _read_only_defaults(self):

fields = [

field for field in self.fields.values()

if (field.read_only) and (field.default != empty) and (field.source != "*") and ("." not in field.source)

]

defaults = OrderedDict()

for field in fields:

try:

default = field.get_default()

except SkipField:

continue

defaults[field.field_name] = default

return defaults

def run_validators(self, value):

"""

Add read_only fields with defaults to value before running validators.

"""

if isinstance(value, dict):

to_validate = self._read_only_defaults()

to_validate.update(value)

else:

to_validate = value

super().run_validators(to_validate)

def to_internal_value(self, data):

"""

Dict of native values <- Dict of primitive datatypes.

"""

if not isinstance(data, Mapping):

message = self.error_messages["invalid"].format(

datatype=type(data).__name__

)

raise ValidationError({

api_settings.NON_FIELD_ERRORS_KEY: [message]

}, code="invalid")

ret = OrderedDict()

errors = OrderedDict()

fields = self._writable_fields

# 针对每一个字段进行验证.

for field in fields:

validate_method = getattr(self, "validate_" + field.field_name, None)

primitive_value = field.get_value(data)

try:

validated_value = field.run_validation(primitive_value)

if validate_method is not None:

validated_value = validate_method(validated_value)

except ValidationError as exc:

errors[field.field_name] = exc.detail

except DjangoValidationError as exc:

errors[field.field_name] = get_error_detail(exc)

except SkipField:

pass

else:

set_value(ret, field.source_attrs, validated_value)

if errors:

raise ValidationError(errors)

return ret

serializers.py 用户自定义的 def validate(self, attrs)

    def run_validation(self, data=empty):

"""

We override the default `run_validation`, because the validation

performed by validators and the `.validate()` method should

be coerced into an error dictionary with a "non_fields_error" key.

"""

(is_empty_value, data) = self.validate_empty_values(data)

if is_empty_value:

return data

value = self.to_internal_value(data)

try:

self.run_validators(value)

value = self.validate(value)

assert value is not None, ".validate() should return the validated data"

except (ValidationError, DjangoValidationError) as exc:

raise ValidationError(detail=as_serializer_error(exc))

return value

def as_serializer_error(exc):

assert isinstance(exc, (ValidationError, DjangoValidationError))

if isinstance(exc, DjangoValidationError):

detail = get_error_detail(exc)

else:

detail = exc.detail

if isinstance(detail, Mapping):

# If errors may be a dict we use the standard {key: list of values}.

# Here we ensure that all the values are *lists* of errors.

return {

key: value if isinstance(value, (list, Mapping)) else [value]

for key, value in detail.items()

}

elif isinstance(detail, list):

# Errors raised as a list are non-field errors.

return {

api_settings.NON_FIELD_ERRORS_KEY: detail

}

# Errors raised as a string are non-field errors.

return {

api_settings.NON_FIELD_ERRORS_KEY: [detail]

}

以上是 tododrf序列化正确抛出异常,给前端 的全部内容, 来源链接: utcz.com/z/511495.html

回到顶部