I want to avoid file duplication for if user already have uploaded an image file in db.
Django ImageField adds an suffix to the image file if the file already exists.
I tried using the solution given by allcaps in following question:
Use already uploaded image in Django's ImageField
But it only gives me an drop-down option in the upload section, but it doesn't contain anything.
Sorry for bothering I forgot to register the model I am using to store images. The answer provided in the link work for me after registering remaining model
Related
I am trying to create a file upload form where a user uploads a file and then I do some processing on it. After processing the file, I want to redirect the user to another form that is partially filled in already from the data I gathered from that file.
I've been reading the docs and found something on multipart forms, but don't know if this is what I should be looking into. I've found example code on uploading files and how to build forms (love Django docs!), but I'm not sure how to tie the two together.
A potential problem I've thought of is how to make sure that a user doesn't somehow skip to the other form without uploading a file. The second form should only be accessible after uploading the file and having it verified for the info I need from it.
You probably want to store the parsed information from the file in the session. That way you can check when displaying the form if the data exists in the session, and if not redirect back to the upload form. If it does exist, you can simply use it as the initial data for the form.
I'm implementing an image upload feature for my Django app (plain Django 1.4 , NOT the non-rel version) running on Google App Engine. The uploaded image is wrapped in a Django model which allows the user to add attributes like a caption and search tags.
The upload is performed by creating a Blobstore upload url through the function call blobstore.create_upload_url(url). The function argument is the url to which the Bobstore redirects when the upload is complete. I want this to be the url of the default Django form handler that performs the save/update of the model that wraps the image so I don't have to duplicate default Django behaviour for form validation, error reporting and database update.
I tried supplying reverse('admin:module_images_add') to create_upload_url() but this doesn't work as it throws an [Errno 30] Read-only file system exception. I presume this originates from the default Django form handler again trying to upload the file the standard Django way but then hits the brick wall of Google App Engine not allowing access to the file system.
At the moment, the only way I can see to get this working without duplicating code is by strictly separating processes: one for defining an image model instance and the second for uploading the actual image. Not very intuitive.
See also this question and answer which I posted earlier.
Any suggestions on how to get this working using one form and reusing Django default form handlers?
EDIT:
I've been reading up on decorators (I'm relatively new to Python) and from what I read, decorators appear to able to modify the behaviour of existing Python code. Would it be possible to change the runtime behaviour of the existing form handler to solve the above using a decorator? I obviously have to (1) develop the decorator and (2) attach it to the default handler. I'm not sure if (2) is possible as it has to be done runtime. I cannot patch the Django code running on GAE...
Well, I finally managed to get this working. Here's what I did in case anyone runs into this as well:
(1) I removed the ImageFile attribute from my model. It ended up causing Django to try and do a file upload from the file system which is not allowed in GAE.
(2) I added a Blobstore key to my model which is basically the key to the GAE BlobStore blob and is required to be able to serve the image at a later stage. On a side note: this attribute has limited length using the GAE SDK but is considerably longer in GAE production. I ended up defining a TextField for it.
(3) Use storage.py with Daniel Roseman's adaption from this question and add the BlobstoreFileUploadHandler to the file handlers in your SETTINGS.PY. It will ensure that the Blobstore key is there in the request for you to save with your model.
(4) I created a custom admin form which contains an ImageField named "image". This is required as it allows you to pick a file. The ImageField is actually "virtual" as its only purpose on the form is to allow me to pick a file for uploading. This is crucial as per (1).
(5) I overwrote render_change_form() method of my ModelAdmin class which will prepare a Blobstore upload url. The upload url has two versions: one for adding new images and one saving changes to existing. Upload urls are passed to the template via the context object.
(6) I modified the change_form.html to include the Blobstore upload url from (5) as the form's action.
(7) I overwrote the save_model() method of my ModelAdmin:
def save_model(self, request, obj, form, change):
if request.FILES.has_key("blobkey"):
blob_key = request.FILES["blobkey"].blobstore_info._BlobInfo__key
obj.blobstore_key = blob_key
super(PhotoFeatureAdmin, self).save_model(request, obj, form, change)
This allows me to retrieve the blob key as set by the upload handler and set it as a property of my model.
For deletion of image models, I added a special function which is triggered by the delete signal of the model. This will keep the Blobstore in sync with the image models in the app.
That's it. The above allows to upload images to the blob store of GAE where each blob is neatly wrapped in a Django model object which admin users can maintain. The good thing is that there's no need to duplicate standard Django behaviour and the model object of the image can easily be extended with attributes in the future.
Final word: in my opinion the support for blobs in plain Django on GAE is currently very poor considering the above. It should be much easier to achieve this, without having to rely on Django non-rel code and a rather long list of modifications; alternatively Google should state something about this in their developer documents. Unless I missed something, this is undocumented territory.
Here's what I want to do, and I did not find something similar in my search so far.
In my admin page, I have a Filefield in my model. The rest of the fields are all read only.
I want to be able to upload a file and process it immediately and to extract info from it to assign to these read only fields.
I thought of overriding the clean_(modelfield) method for this FileField and do this parsing and assigning stuff in it. But this is not done right after the file is uploaded, right? I thought this is done when the form/entry is saved.
Next I thought of adding a custom button to this admin form called 'process' which can be clicked after the file is uploaded. This would trigger the assignment of values to the read only fields.
But I am not able to decide on what is the best approach to process the file and display the updated fields in one page without too much of tinkering.
Any thoughts? Thanks
There are two solutions that I can think of with my limited knowledge. Since, by default, the file upload will only start once the request is posted, an alternative way needs to be designed.
1. Upload file via a script and process the file: Use a script (eg: JQuery script) to upload the file and once upload is complete, trigger a script (onComplete event) to render the values into read-only field. This entire process can be associated to your "Process" button or a time-delayed trigger once the FileField is changed.
2 Custom form for file upload: You can detach the file field and other fields (read only fields that you mentioned). If you design a custom form with just the file upload field and once the user submits the request, you can render another form with rendered initial values in the read only fields. That way you need not have any script but you will have to have 2 forms.
Hope this helps. If you find any other solution, do share it :)
I'm not sure what I am doing wrong. But the uploaded file and it's related cache don't get deleted when the entry is deleted.
I have a photos model inline of a property model, with an FK from the photos model to the property model. I am using 'from sorl.thumbnail import ImageField' to replace the default Django models.ImageField.
In Django Admin, when I delete the entry of a photo, the entry is deleted but the files for that entry are not deleted. I am using Django's runserver for the development and I am not seeing any errors. From what I have read, these files should be removed if the entry is deleted, unless there is a reference to them yet. The only reference that I am seeing yet is in the thumbnail_kvstore table.
Anyone have any thoughts on what I am missing?
The delete_file method will only be called in Django < v1.2.5. The best way to delete sorl.thumbnail.ImageField files, thumbnails and key value store references (used by sorl thumbnail) is to use sorl.thumbnail.delete function: sorl.thumbnail.delete(self.photo)
The ImageField from sorl.thumbnail should be an extension of django's FileField
From the release notes of django 1.2.5:
In earlier Django versions, when a model instance containing a FileField was deleted, FileField took it upon itself to also delete the file from the backend storage. This opened the door to several potentially serious data-loss scenarios, including rolled-back transactions and fields on different models referencing the same file. In Django 1.2.5, FileField will never delete files from the backend storage. If you need cleanup of orphaned files, you'll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).
I had the problem with django-filebrowser, and when you replaced the image with a new one, the cached files did not update. So in my case it wasn't an issue with sorl-thumbnail but rather with django-filebrowser. sorl would only re-draw the thumbnails when the path of the file changed. To fix this I set the filebrowser FILEBROWSER_OVERWRITE_EXISTING setting to False.
FILEBROWSER_OVERWRITE_EXISTING = False
This may help someone at least debug the issue if they are not using django-filebrowser. But in the case of django-filebrowser this is the way to go. Cheers.
I want to upload images to a gallery app. I want the user to be able to either load images normaly, or upload on zip file containing all the images for that gallery. Then it must be uncompressed and all images must be added to that model. This is for the admin site.
Any ideas?
You could either use the existing django-app django-photologue which enables you to do that or have a look at how it is implemented there: https://code.google.com/p/django-photologue/source/browse/trunk/photologue/models.py.
If you see that photlogue is lacking some of the functionality you need, you could also subclass and extend photologue's models in your app!