def perform_action(self, validated_data, instance=None, **kwargs):
new_instance = None
for k, v in validated_data.iteritems():
drf_field = self.fields[k]
if isinstance(drf_field, serializers.BaseSerializer):
value = self._set_new_instance(
new_instance, instance, drf_field, v, **kwargs)
if value:
new_instance = value
elif instance is not None:
self.update_non_model_field(drf_field, instance, v,
validated_data)
else:
self.create_non_model_field(drf_field, v, validated_data)
# In case of an update action where `instance` has specified,
# there is a case when client sent empty data, and, therefore,
# current instance is not updated. Thus, in this case, return
# the current instance instead of the new one.
return new_instance or getattr(self, 'instance', None)
python类BaseSerializer()的实例源码
def proxied(self):
if not self._proxied:
if self.bind_args:
field_name, parent = self.bind_args
if hasattr(parent, 'child') and parent.child is self:
# RecursiveField nested inside of a ListField
parent_class = parent.parent.__class__
else:
# RecursiveField directly inside a Serializer
parent_class = parent.__class__
assert issubclass(parent_class, BaseSerializer)
if self.to is None:
proxied_class = parent_class
else:
try:
module_name, class_name = self.to.rsplit('.', 1)
except ValueError:
module_name, class_name = parent_class.__module__, self.to
try:
proxied_class = getattr(
importlib.import_module(module_name), class_name)
except Exception as e:
raise ImportError(
'could not locate serializer %s' % self.to, e)
# Create a new serializer instance and proxy it
proxied = proxied_class(**self.init_kwargs)
proxied.bind(field_name, parent)
self._proxied = proxied
return self._proxied
def _is_embedded_field(field):
return isinstance(field, BaseSerializer)
def _is_embedded_field(field):
return isinstance(field, BaseSerializer)
def get_nested_serializers(self):
return {k: field for k, field in self.fields.iteritems()
if isinstance(field, serializers.BaseSerializer)}
def __init__(self, query_set=None, serializer_class=None, # noqa
query_params=None, static_filter=None, static_exclude=None,
static_order=None):
"""Initialise view instance."""
if not isinstance(query_params, QueryParams):
raise TypeError("%s not an instance of QueryParams" % query_params)
if not isinstance(query_set, QuerySet):
raise TypeError("%s not an instance of QuerySet" % query_set)
if not issubclass(serializer_class, serializers.BaseSerializer):
raise TypeError("%s not a subclass of BaseSerializer"
% serializer_class)
query = query_params.query
if not query:
self._response = Response(status=status.HTTP_400_BAD_REQUEST)
else:
base = query_set
records_total = base.count()
filter_value = query['search']['value']
filter_query = Q()
exclude_query = Q()
if static_filter:
filter_query |= static_filter
elif filter_value:
filter_cols = []
for col_index in query['columns']:
if query['columns'][col_index]['searchable']:
filter_cols.append(query['columns'][col_index]['name'])
for col in filter_cols:
filter_query |= Q(**{"%s__icontains" % col: filter_value})
if static_exclude:
exclude_query |= static_exclude
filtered = base.filter(filter_query).exclude(exclude_query)
records_filtered = filtered.count()
order_by_columns = list()
if static_order:
order_by_columns.append(static_order)
else:
for i in query['order']:
col_index = query['order'][i]['column']
col_name = query['columns'][col_index]['name']
if query['order'][i]['dir']:
order_by_columns.append("-%s" % col_name)
else:
order_by_columns.append(col_name)
ordered = filtered.order_by(*order_by_columns)
page_start = query['start']
page_end = page_start + query['length']
page = ordered[page_start:page_end]
serializer = serializer_class(
page, many=True, context={'request': query_params.request})
data = serializer.data
response = {
'draw': query['draw'],
'recordsTotal': records_total,
'recordsFiltered': records_filtered,
'data': data,
}
self._response = Response(response)
def _get_field_object(self, request=False):
"""
Creates swagger object for field for request or response
:param request: is this object for request?
:return: swagger object
:rtype: OrderedDict
"""
if isinstance(self._field, BaseSerializer):
if getattr(self._field, 'many', None):
result = {
'type': 'array',
'items': self._serializer_inrospector_class(self._field).build_response_object(),
}
else:
result = self._serializer_inrospector_class(self._field).build_response_object()
else:
field_type, data_type, data_format = self._get_field_type(self._field)
if data_type == 'file' and not request:
data_type = 'string'
result = OrderedDict(type=data_type)
# Retrieve Field metadata
max_val = getattr(self._field, 'max_value', None)
min_val = getattr(self._field, 'min_value', None)
max_length = getattr(self._field, 'max_length', None)
default = self._get_default_value()
description = getattr(self._field, 'help_text', '')
if data_format:
result['format'] = data_format
if max_val is not None and data_type in ('integer', 'number'):
result['minimum'] = min_val
if max_val is not None and data_type in ('integer', 'number'):
result['maximum'] = max_val
if max_length is not None and data_type == 'string':
result['maxLength'] = max_length
if description:
result['description'] = description
if default is not None:
result['default'] = default
if field_type in ['multiple choice', 'choice']:
if isinstance(self._field.choices, dict):
result['enum'] = [k for k in self._field.choices]
if all(isinstance(item, int) for item in result.get('enum', ['1'])):
result['type'] = 'integer'
return result
def _validate_configuration(self):
meta_cls = getattr(self, 'Meta', None)
if meta_cls is None:
raise ex.ApimasException('`Meta` class cannot be found')
model_fields = getattr(meta_cls, 'model_fields', [])
fields = getattr(meta_cls, 'extra_fields', [])
if not (fields or model_fields):
raise ex.ApimasException(
'`extra_fields` and `model_fields` attributes are not'
' specified')
if not (self.model_ser_cls or self.ser_cls):
raise ex.ApimasException(
'A `ContainerSerializer` must define a `ModelSerializer` class'
' or a `Serializer class')
if not (self.model_ser_cls or self.ser_cls):
raise ex.ApimasException(
'A `ContainerSerializer` must include a ModelSerializer'
' and Serializer class')
if self.model_ser_cls:
mro = inspect.getmro(self.model_ser_cls)
if serializers.HyperlinkedModelSerializer not in mro:
raise ex.ApimasException(
'A model serializer class must inherit'
' `serializers.ModelSerializer`')
if self.ser_cls:
mro = inspect.getmro(self.ser_cls)
if serializers.BaseSerializer not in mro:
raise ex.ApimasException(
'A serializer class must implement'
' `serializers.BaseSerializer`')
return model_fields, fields