There are several approaches to uploading files in Django. Each developer faces the most obvious one regularly, when a regular file upload field is used, and it has some known disadvantages. Namely, in case of validation errors the file upload field is reset and the user is forced to select the file again, which is quite tedious. Moreover, in the modern interfaces it is often needed to see the upload result in the form immediately, especially when it comes to the image or when the form is sent with Ajax.
In this article, we will look at two main alternative approaches to the file uploading process:
We will omit the implementation details of the files uploading process on the client side, since it depends heavily on the frontend framework used, and focus on the backend. In any case, the file should be sent using a POST request and included into the request.FILES dictionary on the django side. So:
Generally, with this approach, when a file is sent and saved, a disk path is returned, and this path is used as the string value in the corresponding field of the form. No significant changes of the model are required, and the whole front-end task is reduced to sending file to the server after selecting it, processing the response, and substituting the result in the required field. At the same time, a classic example from the django documentation suggests doing the following:
This is a too low-level approach and it has obvious drawbacks:
It is much easier and more convenient to use the built-in django tools to work with the storage - default_storage. The above example can be transformed as follows:
With this approach, the following advantages are obvious:
As a result, we can get all the necessary data and pass it to the frontend
So, if we need to upload a picture, we can immediately get a link to it and send json to the client side to display the image immediately after uploading, or use it for the further processing (crop, filters, etc.)
In some cases, you need to store additional information about the uploads: who, when uploaded it and so on. For this purpose it makes sense to create a separate model for storing such data and make a link to it in the main model with the foreign key:
Then, our view that deals with processing of file uploads can be modified as follows:
And on the frontend we will fill not the file field, but the object id field for the ForeignKey.
Both of these methods allow you to handle files upload more flexibly and bypass the unpleasant limitation with resetting the file upload field.
In my current project I had a task to use twitter API. Twitter uses OAuth for authentication, which is pretty dreary. To avoid fiddling with it all the time, I've moved authentication to decorator. If key is available - nothing happens, just view is launched as usual. It's convenient that there's no need for additional twitter settings in user profile. Code is in article.
I just found out that __or__ and __and__ are defined for QuerySet. This means that to do queries union or intersection, you can do:User.objects.filter(...) | User.objects.filter(...)User.objects.filter(...) & User.objects.filter(...)
In this article we'll review general approach to working with the best kind of projects - the ones with old untested and undocumented spaghetti code and a tight schedule. We'll review anger management techniques, coping mechanisms and some refactoring tips that might come in handy.