Last active
December 21, 2015 12:49
-
-
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
This file contains 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
''' | |
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 |
@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
This works, however in case you use another storage backend this will cause problem.
My work around is define CharField to overwrite the FileField which cause this Patch problem:
e.g.
class ProfileResource(MultipartResource, ModelResource):
avatar = fields.CharField(attribute= 'avatar') # overwrite the default behavior
avatar_url = fields.FileField(attribute= 'avatar') # use this as the real result