explicitly proxied fields

This commit is contained in:
Warren Jin 2015-01-29 14:07:58 -05:00
parent a63b9fde2e
commit 2970129751
2 changed files with 45 additions and 31 deletions

View File

@ -4,7 +4,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError as DjangoValidationError from django.core.exceptions import ValidationError as DjangoValidationError
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.forms import ImageField as DjangoImageField from django.forms import ImageField as DjangoImageField
from django.utils import six, timezone from django.utils import six, timezone, importlib
from django.utils.dateparse import parse_date, parse_datetime, parse_time from django.utils.dateparse import parse_date, parse_datetime, parse_time
from django.utils.encoding import is_protected_type, smart_text from django.utils.encoding import is_protected_type, smart_text
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -21,7 +21,6 @@ import collections
import copy import copy
import datetime import datetime
import decimal import decimal
import importlib
import inspect import inspect
import re import re
import uuid import uuid
@ -1294,47 +1293,62 @@ class RecursiveField(Field):
next = RecursiveField(allow_null=True) next = RecursiveField(allow_null=True)
""" """
def __init__(self, to='self', to_module=None, **kwargs): # This list of attributes determined by the attributes that
# `rest_framework.serializers` calls to on a field object
PROXIED_ATTRS = (
# bound fields
'get_value',
'get_initial',
'run_validation',
'get_attribute',
'to_representation',
# attributes
'field_name',
'source',
'read_only',
'default',
'source_attrs',
'write_only',
)
def __init__(self, to=None, **kwargs):
self.to = to self.to = to
self.to_module = to_module self.kwargs = kwargs
field_kwargs = dict(
(key, kwargs[key])
for key in kwargs
if key in inspect.getargspec(Field.__init__)
)
super(RecursiveField, self).__init__(**field_kwargs)
def bind(self, field_name, parent): def bind(self, field_name, parent):
super(RecursiveField, self).bind(field_name, parent)
if hasattr(parent, 'child') and parent.child is self: if hasattr(parent, 'child') and parent.child is self:
parent_class = parent.parent.__class__ parent_class = parent.parent.__class__
else: else:
parent_class = parent.__class__ parent_class = parent.__class__
if self.to == 'self': if self.to is None:
proxy_class = parent_class proxied_class = parent_class
else: else:
ref = importlib.import_module(self.to_module or parent_class.__module__) try:
for part in self.to.split('.'): module_name, class_name = self.to.rsplit('.', 1)
ref = getattr(ref, part) except ValueError:
proxy_class = ref module_name, class_name = parent_class.__module__, self.to
proxy = proxy_class(**self._kwargs) try:
proxy.bind(field_name, parent) proxied_class = getattr(
self.proxy = proxy importlib.import_module(module_name), class_name)
except Exception as e:
raise ImportError(
'could not locate serializer %s' % self.to, e)
proxied = proxied_class(**self.kwargs)
proxied.bind(field_name, parent)
self.proxied = proxied
def __getattribute__(self, name): def __getattribute__(self, name):
d = object.__getattribute__(self, '__dict__') if name in RecursiveField.PROXIED_ATTRS:
if 'proxy' in d:
try: try:
attr = getattr(d['proxy'], name) proxied = object.__getattribute__(self, 'proxied')
return getattr(proxied, name)
if hasattr(attr, '__self__'):
return attr
except AttributeError: except AttributeError:
pass pass
return object.__getattribute__(self, name) return object.__getattribute__(self, name)

View File

@ -23,11 +23,11 @@ class PongSerializer(serializers.Serializer):
class SillySerializer(serializers.Serializer): class SillySerializer(serializers.Serializer):
name = serializers.RecursiveField( name = serializers.RecursiveField(
'CharField', 'rest_framework.fields', max_length=5) 'rest_framework.fields.CharField', max_length=5)
blankable = serializers.RecursiveField( blankable = serializers.RecursiveField(
'CharField', 'rest_framework.fields', allow_blank=True) 'rest_framework.fields.CharField', allow_blank=True)
nullable = serializers.RecursiveField( nullable = serializers.RecursiveField(
'CharField', 'rest_framework.fields', allow_null=True) 'rest_framework.fields.CharField', allow_null=True)
links = serializers.RecursiveField('LinkSerializer') links = serializers.RecursiveField('LinkSerializer')
self = serializers.RecursiveField(required=False) self = serializers.RecursiveField(required=False)