Skip to content

Instantly share code, notes, and snippets.

@ratpik
Last active December 21, 2015 12:49
Show Gist options
  • Save ratpik/6308307 to your computer and use it in GitHub Desktop.
Save ratpik/6308307 to your computer and use it in GitHub Desktop.
A simple way to workaround using HTTP PATCH with Django tastypie on models that contain an Image/File Field
'''
I faced a problem when sending a HTTP PATCH to django models containing an ImageField.
The same problem was discussed on the django-tastypie mailing list - https://groups.google.com/forum/?fromgroups#!topic/django-tastypie/cxrI6Cl1z4s
When PATCHing a resource, tasypie dehydrates the original object, merges the changed fields, and then simulates a PUT. This presents a problem for FileField and ImageField as dehydrating these fields produces a URL to the file, rather than the path relative to MEDIA_ROOT stored in the database. Therefore, after a PATCH to a model with FileFields, those fields will contain full URLs rather than relatives paths.
For example, consider a set up in which media for a site is served from http://media.example.com/. When PATCHing a resource containing a file field, a reference to "/directory/file.jpg" will be dehydrated to "http://media.example.com/directory/file.jpg" which is the value that will be written back to the database. - Nikolas Stevenson-Molnar,
The simplest solution I found to this was specifying a custom storage on the django image/file field. The PATCH always stores the relative file path. This works fine to store as well as retrieve using Django-Tastypie
This is possible because of the way tastypie dehydrates filefilds by looking at the url attribute in it. Reference to source - https://github.com/toastdriven/django-tastypie/blob/master/tastypie/fields.py
'''
#From http://stackoverflow.com/questions/1190697/django-filefield-with-upload-to-determined-at-runtime
def custom_file_path(instance, filename):
return '/'.join(['custom', instance.user.username, filename])
#http://stackoverflow.com/questions/1729051/django-upload-to-outside-of-media-root
from django.core.files.storage import FileSystemStorage
fs = FileSystemStorage(location='', base_url='')
from django.db import models
class MyModel(models.Model)
...
picture = models.ImageField(max_length=255, upload_to=custom_file_path, storage=fs, blank=True)
... #Rest of the django model
@teewuane
Copy link

@mave99a, does your fix require the MultipartResource to work? I've been trying and can't get this to work with my setup with just class MyResource(ModelResource):

Edit:

Nevermind, it was some caching that was preventing the change. This solution works great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment