mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-06 13:30:12 +03:00
explicitly proxied fields
This commit is contained in:
parent
a63b9fde2e
commit
2970129751
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user