diff options
| author | Tom Christie | 2014-09-18 14:23:00 +0100 | 
|---|---|---|
| committer | Tom Christie | 2014-09-18 14:23:00 +0100 | 
| commit | 9fdb2280d11db126771686d626aa8a0247b8a46c (patch) | |
| tree | 4dd3e7d39e2bff75f38ed0a748befa478ff889a1 /rest_framework/relations.py | |
| parent | 3bc628edc01a6bd4feeceaefa45168549b79a31a (diff) | |
| download | django-rest-framework-9fdb2280d11db126771686d626aa8a0247b8a46c.tar.bz2 | |
First pass on ManyRelation
Diffstat (limited to 'rest_framework/relations.py')
| -rw-r--r-- | rest_framework/relations.py | 42 | 
1 files changed, 41 insertions, 1 deletions
| diff --git a/rest_framework/relations.py b/rest_framework/relations.py index 9f44ab63..474d3e75 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -10,7 +10,6 @@ from django.utils.translation import ugettext_lazy as _  class RelatedField(Field):      def __init__(self, **kwargs):          self.queryset = kwargs.pop('queryset', None) -        self.many = kwargs.pop('many', False)          assert self.queryset is not None or kwargs.get('read_only', None), (              'Relational field must provide a `queryset` argument, '              'or set read_only=`True`.' @@ -21,6 +20,13 @@ class RelatedField(Field):          )          super(RelatedField, self).__init__(**kwargs) +    def __new__(cls, *args, **kwargs): +        # We override this method in order to automagically create +        # `ManyRelation` classes instead when `many=True` is set. +        if kwargs.pop('many', False): +            return ManyRelation(child_relation=cls(*args, **kwargs)) +        return super(RelatedField, cls).__new__(cls, *args, **kwargs) +      def get_queryset(self):          queryset = self.queryset          if isinstance(queryset, QuerySet): @@ -216,3 +222,37 @@ class SlugRelatedField(RelatedField):      def to_representation(self, obj):          return getattr(obj, self.slug_field) + + +class ManyRelation(Field): +    """ +    Relationships with `many=True` transparently get coerced into instead being +    a ManyRelation with a child relationship. + +    The `ManyRelation` class is responsible for handling iterating through +    the values and passing each one to the child relationship. + +    You shouldn't need to be using this class directly yourself. +    """ + +    def __init__(self, child_relation=None, *args, **kwargs): +        self.child_relation = child_relation +        assert child_relation is not None, '`child_relation` is a required argument.' +        super(ManyRelation, self).__init__(*args, **kwargs) + +    def bind(self, field_name, parent, root): +        # ManyRelation needs to provide the current context to the child relation. +        super(ManyRelation, self).bind(field_name, parent, root) +        self.child_relation.bind(field_name, parent, root) + +    def to_internal_value(self, data): +        return [ +            self.child_relation.to_internal_value(item) +            for item in data +        ] + +    def to_representation(self, obj): +        return [ +            self.child_relation.to_representation(value) +            for value in obj.all() +        ] | 
