Django rest framework - thumbnail image serializer - django

My case is basic: I want to send urls of thumbnails to the client within responses to AJAX requests. I have custom image fields that deserialize base64 encoded images from the client and sorl_thumbnail as thumbnail engine. In my views I want to instantiate deserializer with arbitrary options for thumbnailer.
What is a common techniques for that in Django REST framework?
upd
The main problem is how to pass arguments about dimensions, format, quality, etc, to serializer? In one place I might need small thumbnail of the picture, in other bigger thumbnail.
Now I see two approaches:
- Make a factory which will produce serializer with given options for thumbnail-fields
- Send thumbnail options within AJAX requests and make serializer able to read and follow them.

There are lots of ways you could go about this, depending on a lot of information you don't give, but, perhaps look into using a SerializerMethodField in your serializer.
The basic idea would be to create a method that is able to return the appropriate URL for the thumbnail given the object instance and bind the SerializerMethodField to that.
By default DRF's GenericViews pass the request through to serializers via the context parameter. This enables you to access the request with such as request = self.context.get('request', None). From there you can read the thumbnail options as you suggest.
Hopefully that's enough to get you started.

Related

Advantages of django rest_framework over AJAX and JsonResponce

I can get data in JSON format, using a view and url by calling an AJAX function from JQuery. Which only needs to create a view and a url to access it. But is rest_framework to do the same thing I need to create serializer, views and a url to do the same. So is it good to use AJAXX in these cases or I need to use rest_framework every time.
Thanks.
Your question is not clear, From my understanding you want to know Why Django rest framework instead of JSONResponse?
JSONResponse:
JSONResponse will simply convert your model object to json response. You have restriction in formats and it's not efficient method when u have large dataset.
For more reference refer here
DRF:
Browsable API.
Serialization that supports both ORM and non-ORM data sources.
You don't need to write all the CRUD methods everytime.
The main advantage to use DRF is ModelViewset and Serialization. With the use of serializer you can access Related data(Foreign key & Many-to-Many) easily.
From my Opinion, if you have extensive API requirements, you can use the Django rest framework otherwise don't choose that.
Check this reference and decide based on your requirements.
https://medium.com/profil-software-blog/10-things-you-need-to-know-to-effectively-use-django-rest-framework-7db7728910e0
https://medium.com/crowdbotics/how-to-write-an-api-in-3-lines-of-code-with-django-rest-framework-59b0971edfa4

Django Rest framework Serializer necessary?

I had one business requirement to be implemented lately which required me to just fetch the data and render the response.
So some API endpoint would return a response as: [{"id" :1,"name":"first"} ,{"id" :2,"name":"second":}]
Can I just render this data by constructing a list of dictionaries which can be populated with various ORM queries instead of rendering the response through a serializer?
Would it be an efficient solution in case I won't be using this serializer ever for POST request?
It is fine to have Django Rest Framework without serializer.
But best practice would be using Serializer.
Using Serializer you can control the input and out of the data.
You can validate Data. You can serializer and deserializer the data. Much more than that. Think Serializer as Form
From the Docs
Expanding the usefulness of the serializers is something that we would
like to address. However, it's not a trivial problem, and it will take
some serious design work.
— Russell Keith-Magee, Django users group

User controlled presentation of data in widgets on a dashboard app - Best Practices?

Consider a very simple dashboard application in Django. It has 2 models:
Page
Widget
Naturally, Page and Widget have a ManyToMany relationship.
Like any good dashboard implementation, the designers can change 3 things in a widget:
Data source that drives the widget
Placement of widget on the Page
Presentation of Data inside a widget
The Data is specified using a URL field in the Widget and is being served by a REST API based on Django REST Framework with the django-filter backend.
The Placement on the Page is catered using the excellent Gridster.
This leaves the Presentation part. I have two possible solutions:
Attach a template TextField with the Widget. Data will be fetched from web services in JSON format and rendered according to the template (handlebars) defined in Widget on the client side.
Pass the template name as query string in the URL to the REST API and render the Data using the user-specified template.
Now that the context is clearly defined (hopefully), following are my questions:
Is there any way I can choose the first solution and still be able to use the automatic forms generated by the DRF Serializers?
If not, and I choose the second solution, are there any potential pit-falls regarding security, code maintenance, code quality, testing and the like? Why have I not seen anyone else doing this i.e. letting the user select the template via query string?
Is there any other solution that I am missing?
Your first options seems most promising: fetch the data as JSON and insert it into templates on the client. All good.
So can you do that "and still be able to use the automatic forms generated by the DRF Serializers"? — Short answer, it depends what you mean by "automatic forms".
Serializers take a data dictionary, validate it and (for ModelSerializer subclasses) convert it into a (model) object instance for you. If by "automatic forms" you mean will you still be able to this validation behaviour, then the answer is yes. Create your JSON payload on the client and send an appropriate HTTP request to the API. Django Rest Framework's Serializers will work as expected.
If (though) by "automatic forms" you mean will you still be able to use the HTML forms that DRF provides in its web broweasble API, then the answer is no. The browseable API is built around an HTML renderer returning entire web pages. These include a pretty-printed representation of the JSON you'll be using as well as the web-forms that, on this assumption, you're interested in.
If you go this route you'll need to generate the forms on the client, using whatever model, view, template and binding features your chosen library (libraries?) offer(s).
I hope that helps. Good luck.

More Blobstore upload woes with standard Django

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.

Django REST API to receive images

I have a Django project using Tastypie as its main API and it works ok. But now I want to be able to receive images through the API (coming from phones and such). It looks like Tastypie is not quite ready yet in that field. I'm ready to try something else just for that matter, or even write a custom view. How can I do that?
A standard Django view can technically serve as an API endpoint, too, so why not just write a view that handles a POST payload?
You could even make a form which you use to validate the input, even if your client device isn't using that form to capture content - as long as the fields and their criteria match up, it'll still fit.