|
4 | 4 |
|
5 | 5 | from django.conf import settings |
6 | 6 | from django.http import HttpResponse |
| 7 | +from django.core.exceptions import ObjectDoesNotExist |
7 | 8 | from django.core.urlresolvers import reverse |
8 | 9 | from django.utils.encoding import force_text |
9 | 10 |
|
| 11 | +import tastypie |
10 | 12 | from tastypie.api import Api |
11 | 13 | from tastypie.bundle import Bundle |
12 | 14 | from tastypie.serializers import Serializer as BaseSerializer |
@@ -172,5 +174,42 @@ def hydrate(self, bundle): |
172 | 174 | raise ApiFieldError("Datetime provided to '%s' field must be a string: %s" % (self.instance_name, value)) |
173 | 175 |
|
174 | 176 | return value |
175 | | - |
176 | | - |
| 177 | + |
| 178 | +class ToOneField(tastypie.fields.ToOneField): |
| 179 | + "Subclass of tastypie.fields.ToOneField which adds caching in the dehydrate method." |
| 180 | + |
| 181 | + def dehydrate(self, bundle, for_list=True): |
| 182 | + foreign_obj = None |
| 183 | + |
| 184 | + if callable(self.attribute): |
| 185 | + previous_obj = bundle.obj |
| 186 | + foreign_obj = self.attribute(bundle) |
| 187 | + elif isinstance(self.attribute, six.string_types): |
| 188 | + foreign_obj = bundle.obj |
| 189 | + |
| 190 | + for attr in self._attrs: |
| 191 | + previous_obj = foreign_obj |
| 192 | + try: |
| 193 | + foreign_obj = getattr(foreign_obj, attr, None) |
| 194 | + except ObjectDoesNotExist: |
| 195 | + foreign_obj = None |
| 196 | + |
| 197 | + if not foreign_obj: |
| 198 | + if not self.null: |
| 199 | + if callable(self.attribute): |
| 200 | + raise ApiFieldError("The related resource for resource %s could not be found." % (previous_obj)) |
| 201 | + else: |
| 202 | + raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr)) |
| 203 | + return None |
| 204 | + |
| 205 | + fk_resource = self.get_related_resource(foreign_obj) |
| 206 | + |
| 207 | + # Up to this point we've copied the code from tastypie 0.13.1. Now |
| 208 | + # we add caching. |
| 209 | + cache_key = fk_resource.generate_cache_key('related', for_list=for_list) |
| 210 | + dehydrated = fk_resource._meta.cache.get(cache_key) |
| 211 | + if dehydrated is None: |
| 212 | + fk_bundle = Bundle(obj=foreign_obj, request=bundle.request) |
| 213 | + dehydrated = self.dehydrate_related(fk_bundle, fk_resource, for_list=for_list) |
| 214 | + fk_resource._meta.cache.set(cache_key, dehydrated) |
| 215 | + return dehydrated |
0 commit comments