Created
December 2, 2013 12:39
-
-
Save johanneskoch/7748883 to your computer and use it in GitHub Desktop.
Mixins that can be used to easily create nested Tastypie resources. If you for example have a child resource accessible at /api/child-resources/ related to a parent resource accessible at /api/parent-resources/, these would create a URL structure like /api/parent-resources/{detail_uri_name}/child-resources/ that would allow you to access the chi…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from django.conf.urls.defaults import url | |
| from django.db.models.sql.constants import LOOKUP_SEP | |
| from tastypie.utils import trailing_slash | |
| class ParentResourceMixin(object): | |
| """ NOTE: Needs to be filterable on detail_uri_name if not pk """ | |
| def prepend_urls(self): | |
| urls = [] | |
| for child_resource in self._meta.child_resources: | |
| child = child_resource() | |
| related_name = child.reverse_field_lookup(self) | |
| if related_name is None: | |
| continue | |
| related_lookup = [related_name] | |
| if self._meta.detail_uri_name != 'pk': | |
| related_lookup.append(self._meta.detail_uri_name) | |
| related_lookup = LOOKUP_SEP.join(related_lookup) | |
| urls += [ | |
| url( | |
| r'^%s/(?P<%s>\w[\w/-]*)/(?P<resource_name>%s)%s$' % ( | |
| self._meta.resource_name, | |
| related_lookup, | |
| child._meta.resource_name, | |
| trailing_slash(), | |
| ), | |
| child.wrap_view('nested_dispatch_list'), | |
| {'parent_resource': self, 'parent_lookup': related_lookup}, | |
| 'api_nested_dispatch_list', | |
| ), | |
| url( | |
| r'^%s/(?P<%s>\w[\w/-]*)/(?P<resource_name>%s)/(?P<%s>\w[\w/-]*)%s$' % ( | |
| self._meta.resource_name, | |
| related_lookup, | |
| child._meta.resource_name, | |
| child._meta.detail_uri_name, | |
| trailing_slash(), | |
| ), | |
| child.wrap_view('nested_dispatch_detail'), | |
| {'parent_resource': self, 'parent_lookup': related_lookup}, | |
| 'api_nested_dispatch_detail', | |
| ), | |
| ] | |
| return urls | |
| class ChildResourceMixin(object): | |
| """ NOTE: Needs to be filterable on all parent resources """ | |
| def reverse_field_lookup(self, resource_instance): | |
| for field_name, field_object in self.fields.items(): | |
| if not getattr(field_object, 'is_related', False): | |
| continue | |
| if isinstance(resource_instance, field_object.to_class): | |
| return field_name | |
| return None | |
| def get_parent_obj(self, bundle): | |
| lookup_key = bundle.request.parent_lookup_key | |
| lookup_value = bundle.request.parent_lookup_value | |
| return bundle.request.parent_resource.obj_get( | |
| bundle, **{lookup_key: lookup_value}) | |
| def nested_dispatch_list(self, request, **kwargs): | |
| return self.nested_dispatch('list', request, **kwargs) | |
| def nested_dispatch_detail(self, request, **kwargs): | |
| return self.nested_dispatch('detail', request, **kwargs) | |
| def nested_dispatch(self, request_type, request, **kwargs): | |
| lookup = kwargs.pop('parent_lookup') | |
| try: | |
| lookup_key = lookup.split(LOOKUP_SEP)[1] | |
| except IndexError: | |
| lookup_key = 'pk' | |
| request.is_nested = True | |
| request.parent_resource = kwargs.pop('parent_resource') | |
| request.parent_lookup_key = lookup_key | |
| request.parent_lookup_value = kwargs[lookup] | |
| return getattr(self, 'dispatch_%s' % request_type)(request, **kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment