|
3 | 3 | from rest_framework.fields import MISSING_ERROR_MESSAGE
|
4 | 4 | from rest_framework.relations import *
|
5 | 5 | from django.utils.translation import ugettext_lazy as _
|
| 6 | +from django.db.models.query import QuerySet |
6 | 7 |
|
7 | 8 | from rest_framework_json_api.exceptions import Conflict
|
8 | 9 | from rest_framework_json_api.utils import Hyperlink, \
|
@@ -168,11 +169,50 @@ def choices(self):
|
168 | 169 | ])
|
169 | 170 |
|
170 | 171 |
|
| 172 | + |
171 | 173 | class SerializerMethodResourceRelatedField(ResourceRelatedField):
|
| 174 | + """ |
| 175 | + Allows us to use serializer method RelatedFields |
| 176 | + with return querysets |
| 177 | + """ |
| 178 | + def __new__(cls, *args, **kwargs): |
| 179 | + """ |
| 180 | + We override this because getting serializer methods |
| 181 | + fails at the base class when many=True |
| 182 | + """ |
| 183 | + if kwargs.pop('many', False): |
| 184 | + return cls.many_init(*args, **kwargs) |
| 185 | + return super(ResourceRelatedField, cls).__new__(cls, *args, **kwargs) |
| 186 | + |
| 187 | + def __init__(self, child_relation=None, *args, **kwargs): |
| 188 | + # DRF 3.1 doesn't expect the `many` kwarg |
| 189 | + kwargs.pop('many', None) |
| 190 | + model = kwargs.pop('model', None) |
| 191 | + if model: |
| 192 | + self.model = model |
| 193 | + super(SerializerMethodResourceRelatedField, self).__init__(child_relation, *args, **kwargs) |
| 194 | + |
| 195 | + @classmethod |
| 196 | + def many_init(cls, *args, **kwargs): |
| 197 | + list_kwargs = {'child_relation': cls(*args, **kwargs)} |
| 198 | + for key in kwargs.keys(): |
| 199 | + if key in ('model',) + MANY_RELATION_KWARGS: |
| 200 | + list_kwargs[key] = kwargs[key] |
| 201 | + return SerializerMethodResourceRelatedField(**list_kwargs) |
| 202 | + |
172 | 203 | def get_attribute(self, instance):
|
173 | 204 | # check for a source fn defined on the serializer instead of the model
|
174 | 205 | if self.source and hasattr(self.parent, self.source):
|
175 | 206 | serializer_method = getattr(self.parent, self.source)
|
176 | 207 | if hasattr(serializer_method, '__call__'):
|
177 | 208 | return serializer_method(instance)
|
178 |
| - return super(ResourceRelatedField, self).get_attribute(instance) |
| 209 | + return super(SerializerMethodResourceRelatedField, self).get_attribute(instance) |
| 210 | + |
| 211 | + def to_representation(self, value): |
| 212 | + if isinstance(value, QuerySet): |
| 213 | + base = super(SerializerMethodResourceRelatedField, self) |
| 214 | + return [base.to_representation(x) for x in value] |
| 215 | + return super(SerializerMethodResourceRelatedField, self).to_representation(value) |
| 216 | + |
| 217 | + def get_links(self, obj=None, lookup_field='pk'): |
| 218 | + return OrderedDict() |
0 commit comments