def setUp(self):
from django.contrib.auth.models import Permission, Group
from .models import User, Skill
# in django.contrib.auth.models
# permission *-* group, permission *-* user, permission *-* groups
# in my tests.models:
# skill *- user
class ContribPermissionSerializer(serializers.ModelSerializer):
class Meta:
model = Permission
fields = "__all__"
class SkillSerializer(serializers.ModelSerializer):
class Meta:
model = Skill
fields = "__all__"
class UserSerializer(serializers.ModelSerializer):
skills = SkillSerializer(many=True)
permissions = ContribPermissionSerializer(many=True)
class Meta:
model = User
fields = "__all__"
class ContribGroupSerializer(serializers.ModelSerializer):
permissions = ContribPermissionSerializer(many=True)
users = UserSerializer(many=True)
class Meta:
model = Group
fields = "__all__"
self.PermissionSerializer = ContribPermissionSerializer
self.SkillSerializer = SkillSerializer
self.UserSerializer = UserSerializer
self.GroupSerializer = ContribGroupSerializer
python类ModelSerializer()的实例源码
def to_representation(self, obj):
if isinstance(obj,UserProfile):
return super(UserProfileSerializer,self).to_representation(obj)
serializer = TokenSerializer(obj)
return serializer.data
# class ScoreSerializer(serializers.ModelSerializer):
# UserId = serializers.IntegerField(source='GiverPersonId_id',read_only=True) #Read olurken hangi user in verdigini anlamak icin kullanilir
# Score = serializers.IntegerField(source='Point')
# Name = serializers.CharField(source='GiverPersonId.user.first_name',read_only=True)
# Image = serializers.ImageField(source='GiverPersonId.Photo', max_length=None, use_url=True, read_only=True)
# class Meta(object):
# model = Score
# fields = ('Score','UserId','Name','Image')
# def create(self, validated_data):
# taker = self.context['view'].kwargs['pk']
# score = Score.objects.create(TakerPersonId_id=taker ,GiverPersonId_id=self.context['request'].user.id, **validated_data)
# scores = Score.objects.filter(TakerPersonId_id=taker)
# total = 0.0
# for score in scores:
# total += score.Point
# avarage_score = total / len(scores)
# user = UserProfile.objects.get(pk=taker)
# user.Score = avarage_score
# user.save()
# return {'IsSuccess':True,'context':''}
# def to_representation(self, obj):
# if isinstance(obj,Score):
# return super(ScoreSerializer,self).to_representation(obj)
# serializer = ResultSerializer(obj)
# return serializer.data
def test_default_modelserializer_field(self):
class ArtistSerializer(serializers.ModelSerializer):
class Meta:
model = Artist
fields = ('id', 'name')
with self.assertRaises(exceptions.ImproperlyConfigured):
ArtistSerializer().fields() # Fields aren't built until first accessed
def get_serializer_class(self):
if self.serializer_class is None:
class AutoConfigModelSerializer(ModelSerializer):
"""Serializer class for configuration models."""
class Meta(object):
"""Meta information for AutoConfigModelSerializer."""
model = self.model
self.serializer_class = AutoConfigModelSerializer
return self.serializer_class
def get_raw_type_from_serializer_field(field):
if isinstance(field, ListSerializer):
return 'list'
if isinstance(field, ModelSerializer):
return 'model'
# return smart_text(field.Meta.model.__name__).lower()
name = field.__class__.__name__
if name.endswith('Field'):
name = smart_text(name[:-5])
return smart_text(name).lower()
def _build_serializer(self, serializer_class, fields=None, instance=None):
if serializer_class is None:
return None
kwargs = {}
if hasattr(self, 'initial_data'):
# Route initial data to the corresponding child serializer, e.g.
# model data --> ModelSerializer.
initial_data = self.initial_data or {}
data = {k: v for k, v in initial_data.iteritems()
if k in fields}
kwargs['data'] = data
return serializer_class(
context=self._context, partial=self.partial, instance=instance,
**kwargs)
def generate_model_serializer(name, model, model_fields, bases=None):
"""
Generates a `ModelSerializer` given the model_fields.
The specified `model_fields` is a tuple of model fields properties and
the already created drf_fields. The former are passed to the `Meta` class
of serializer in order to be created afterwards, whereas the latter are
specified directly to the serializer class.
"""
field_properties, drf_fields = classify_model_fields(
model_fields)
if not (field_properties or drf_fields):
return None
drf_fields = drf_fields or {}
meta_cls_content = {
'model': model,
'fields': drf_fields.keys() + field_properties.keys(),
'extra_kwargs': field_properties,
}
cls_content = {
field_name: serializer
for field_name, serializer in drf_fields.iteritems()
}
custom_bases = map(utils.LOAD_CLASS, bases or [])
base_cls = tuple(custom_bases) + (ApimasModelSerializer,)
meta_cls = type('Meta', (object,), meta_cls_content)
cls_content['Meta'] = meta_cls
return type(name, base_cls, cls_content)
def _extract_field_info(self, model, field_name, field, fields, relationships, adapter, target_app, allow_recursion=False):
if field_name == 'id':
return None
field_item = {
'name': field_name,
'type': adapter.field_type_mapping[field.__class__.__name__]
}
if isinstance(field, PrimaryKeyRelatedField) or isinstance(field, ManyRelatedField) \
or isinstance(field, ModelSerializer):
if model is None:
field_item['related_model'] = field.queryset.model._meta.model_name.lower()
field_item['app'] = target_app if target_app is not None else \
field.queryset.model._meta.app_label.lower()
relationships.append(field_item)
else:
model_field = model._meta.get_field(field_name)
field_item['related_model'] = model_field.related_model._meta.model_name.lower()
field_item['app'] = target_app if target_app is not None else \
model_field.related_model._meta.app_label.lower()
relationships.append(field_item)
if hasattr(model_field, 'field'):
field_item['inverse'] = model_field.field.name
elif hasattr(model_field, 'remote_field') and \
getattr(model_field.remote_field, 'related_name', None) is not None:
field_item['inverse'] = model_field.remote_field.related_name
if field_item.get('inverse', '-')[-1] == '+':
field_item.pop('inverse')
if isinstance(field, ModelSerializer):
if hasattr(field, 'many') and field.many:
field_item['type'] = adapter.field_type_mapping['ManyRelatedField']
else:
field_item['type'] = adapter.field_type_mapping['PrimaryKeyRelatedField']
elif isinstance(field, ModelSerializer):
field_item['related_model'] = field.queryset.model._meta.model_name.lower()
field_item['app'] = target_app if target_app is not None else \
field.queryset.model._meta.app_label.lower()
relationships.append(field_item)
if field.many:
field_item['type'] = adapter.field_type_mapping['ManyRelatedField']
else:
field_item['type'] = adapter.field_type_mapping['PrimaryKeyRelatedField']
elif isinstance(field, ListSerializer):
child_rels = []
child_fields = []
self._extract_field_info(model, field_name, field.child, child_fields, child_rels, adapter, target_app)
if len(child_rels) > 0:
for item in child_rels:
item['type'] = adapter.field_type_mapping['ManyRelatedField']
item.pop('inverse', None)
relationships.append(item)
else:
field_item['type'] = adapter.field_type_mapping('ListField')
fields.append(field_item)
else:
fields.append(field_item)
return field_item
def update(self, instance, validated_data):
reverse_relations = OrderedDict()
relations = OrderedDict()
# Sort fields by create priority
fields = self.get_sorted_by_create_priority(self.fields)
# Remove related fields from validated data for future manipulations
for field_name, field in fields.items():
if field.read_only:
continue
if isinstance(field, serializers.ListSerializer):
if isinstance(field.child, serializers.ModelSerializer):
if validated_data.pop(field.source, None) is None:
# Skip field if field is not required or null allowed
continue
reverse_relations[field_name] = field.child
if isinstance(field, serializers.ModelSerializer):
if validated_data.pop(field.source, None) is None:
# Skip field if field is not required or null allowed
continue
relations[field_name] = field
nested_related_kwarg = getattr(self.Meta, 'nested_related_kwarg', None)
if reverse_relations:
assert nested_related_kwarg, \
"Set `nested_related_kwarg` in Meta options for use nested " \
"create feature"
if relations:
raise NotImplementedError("NestedUpdateMixin not provide update "
"for direct relations")
# Update instance
instance = super(NestedUpdateMixin, self).update(
instance, validated_data)
if reverse_relations:
self.update_reverse_relations(instance, reverse_relations)
self.delete_reverse_relations_if_need(instance, reverse_relations)
return instance
def create(self, validated_data):
reverse_relations = OrderedDict()
relations = OrderedDict()
# Sort fields by create priority
fields = self.get_sorted_by_create_priority(self.fields)
# Remove related fields from validated data for future manipulations
for field_name, field in fields.items():
if field.read_only or field_name in self._ignore_creation:
continue
if isinstance(field, serializers.ListSerializer):
if isinstance(field.child, serializers.ModelSerializer):
if validated_data.pop(field.source, None) is None:
# Skip field if field is not required or null allowed
continue
reverse_relations[field_name] = field.child
if isinstance(field, serializers.ModelSerializer):
if validated_data.pop(field.source, None) is None:
# Skip field if field is not required or null allowed
continue
relations[field_name] = field
nested_related_kwarg = getattr(self.Meta, 'nested_related_kwarg', None)
if reverse_relations:
assert nested_related_kwarg, \
"Set `nested_related_kwarg` in Meta options for use nested " \
"create feature"
# Create direct relations (foreign key)
for field_name, field in relations.items():
serializer = self._get_new_serializer(
field, data=self.initial_data[field_name])
serializer.is_valid(raise_exception=True)
validated_data[field.source] = serializer.save()
# Create instance
instance = super(NestedCreateMixin, self).create(validated_data)
if reverse_relations:
self.create_reverse_relations(instance, reverse_relations)
return instance
def modelserializer_factory(model, serializer=serializers.ModelSerializer, fields=None, exclude=None, **kwargs):
"""
Generate serializer basing on django's modelform_factory
:param model: model we create serializer for
:param serializer: base serializer class
:param fields: list of fields to include in serializer
:param exclude: list of fields to exclude from serializer
:param kwargs: fields mapping
:return:
"""
# TODO: decide if we need cache and what to do with parameters tha can be different
serializer_class = serializer_cache.get(model, None)
if serializer_class:
return serializer_class
def _get_declared_fields(attrs):
fields = [(field_name, attrs.pop(field_name))
for field_name, obj in list(attrs.items())
if isinstance(obj, serializers.Field)]
fields.sort(key=lambda x: x[1]._creation_counter)
return OrderedDict(fields)
meta_attrs = {'model': model}
if fields is not None:
meta_attrs['fields'] = fields
if exclude is not None:
meta_attrs['exclude'] = exclude
if fields is None and exclude is None:
meta_attrs['fields'] = '__all__'
parent = (object, )
Meta = type(str('Meta'), parent, meta_attrs)
class_name = model.__name__ + str('Serializer')
serializer_class_attrs = {
'Meta': Meta,
'_get_declared_fields': _get_declared_fields(kwargs),
}
serializer_class = type(serializer)(class_name, (serializer,), serializer_class_attrs)
serializer_cache[model] = serializer_class
return serializer_class
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