|
3 | 3 | """ |
4 | 4 | import inflection |
5 | 5 |
|
6 | | - |
7 | 6 | from django.core import urlresolvers |
8 | 7 | from django.conf import settings |
9 | 8 | from django.utils import six, encoding |
10 | 9 | from django.utils.six.moves.urllib.parse import urlparse, urlunparse |
11 | 10 | from django.utils.translation import ugettext_lazy as _ |
12 | 11 |
|
13 | | -from rest_framework.serializers import Serializer, BaseSerializer |
14 | | -from rest_framework.relations import RelatedField |
| 12 | +from rest_framework.serializers import BaseSerializer |
| 13 | +from rest_framework.relations import RelatedField, HyperlinkedRelatedField |
15 | 14 | from rest_framework.settings import api_settings |
16 | 15 | from rest_framework.exceptions import APIException |
17 | 16 |
|
|
25 | 24 | except ImportError: |
26 | 25 | ManyRelatedField = type(None) |
27 | 26 |
|
28 | | -try: |
29 | | - from rest_framework.serializers import ListSerializer |
30 | | -except ImportError: |
31 | | - ListSerializer = type(None) |
32 | | - |
33 | 27 |
|
34 | 28 | def get_resource_name(context): |
35 | 29 | """ |
@@ -58,13 +52,13 @@ def get_resource_name(context): |
58 | 52 | # Check the meta class |
59 | 53 | resource_name = ( |
60 | 54 | getattr(view, 'serializer_class') |
61 | | - .Meta.resource_name) |
| 55 | + .Meta.resource_name) |
62 | 56 | except AttributeError: |
63 | 57 | # Use the model |
64 | 58 | try: |
65 | 59 | resource_name = ( |
66 | 60 | getattr(view, 'serializer_class') |
67 | | - .Meta.model.__name__) |
| 61 | + .Meta.model.__name__) |
68 | 62 | except AttributeError: |
69 | 63 | try: |
70 | 64 | resource_name = view.model.__name__ |
@@ -121,28 +115,61 @@ def format_keys(obj, format_type=None): |
121 | 115 | return obj |
122 | 116 |
|
123 | 117 |
|
| 118 | +def extract_id_from_url(url): |
| 119 | + http_prefix = url.startswith(('http:', 'https:')) |
| 120 | + if http_prefix: |
| 121 | + # If needed convert absolute URLs to relative path |
| 122 | + data = urlparse(url).path |
| 123 | + prefix = urlresolvers.get_script_prefix() |
| 124 | + if data.startswith(prefix): |
| 125 | + url = '/' + data[len(prefix):] |
| 126 | + |
| 127 | + match = urlresolvers.resolve(url) |
| 128 | + return encoding.force_text(match.kwargs['pk']) |
| 129 | + |
| 130 | + |
124 | 131 | def extract_id(fields, resource): |
125 | 132 | for field_name, field in six.iteritems(fields): |
126 | 133 | if field_name == 'id': |
127 | 134 | return encoding.force_text(resource[field_name]) |
128 | 135 | if field_name == api_settings.URL_FIELD_NAME: |
129 | | - url = resource[field_name] |
130 | | - http_prefix = url.startswith(('http:', 'https:')) |
131 | | - if http_prefix: |
132 | | - # If needed convert absolute URLs to relative path |
133 | | - data = urlparse(url).path |
134 | | - prefix = urlresolvers.get_script_prefix() |
135 | | - if data.startswith(prefix): |
136 | | - url = '/' + data[len(prefix):] |
137 | | - |
138 | | - match = urlresolvers.resolve(url) |
139 | | - return encoding.force_text(match.kwargs['pk']) |
| 136 | + return extract_id_from_url(resource[field_name]) |
140 | 137 |
|
141 | 138 |
|
142 | 139 | def extract_attributes(fields, resource): |
143 | 140 | data = OrderedDict() |
144 | 141 | for field_name, field in six.iteritems(fields): |
145 | | - if not (isinstance(field, RelatedField) or isinstance(field, BaseSerializer)): |
146 | | - data.update({field_name: encoding.force_text(resource[field_name])}) |
| 142 | + # Skip fields with relations |
| 143 | + if isinstance(field, (RelatedField, BaseSerializer, ManyRelatedField)): |
| 144 | + continue |
| 145 | + |
| 146 | + data.update({field_name: encoding.force_text(resource[field_name])}) |
| 147 | + |
| 148 | + return format_keys(data) |
| 149 | + |
| 150 | + |
| 151 | +def extract_relationships(fields, resource): |
| 152 | + data = OrderedDict() |
| 153 | + for field_name, field in six.iteritems(fields): |
| 154 | + # Skip URL field |
| 155 | + if field_name == api_settings.URL_FIELD_NAME: |
| 156 | + continue |
| 157 | + |
| 158 | + # Skip fields without relations |
| 159 | + if not isinstance(field, (RelatedField, BaseSerializer, ManyRelatedField)): |
| 160 | + continue |
| 161 | + |
| 162 | + if isinstance(field, ManyRelatedField): |
| 163 | + relation_data = list() |
| 164 | + |
| 165 | + relation = field.child_relation |
| 166 | + model = relation.queryset.model |
| 167 | + relation_type = inflection.pluralize(model.__name__).lower() |
| 168 | + |
| 169 | + if isinstance(relation, HyperlinkedRelatedField): |
| 170 | + for link in resource[field_name]: |
| 171 | + relation_data.append(OrderedDict([('type', relation_type), ('id', extract_id_from_url(link))])) |
| 172 | + |
| 173 | + data.update({field_name: {'data': relation_data}}) |
147 | 174 |
|
148 | 175 | return format_keys(data) |
0 commit comments