izimobil/django-rest-framework-datatables

Using "format" as a GET Param breaks DRF

Closed this issue · 10 comments

How laconic...
Can you describe the issue, please ? What's the problem with the "format" GET parameter ?

Ah forgive me for not including more detail, the main issue is when using the query parameter format=datatables in my request I'm returned a 404, not really sure why this is happening, haven't had time to really dive into it

Ah found out what was wrong, the project I was working on had a drf settings object in it's dev settings and I was only editing the base settings haha, false alarm

In case anyone else runs into this, I was unable to use format as a query parameter to a ViewSet because of this. It seems that format is reserved for DRF.

To fix the issue, change the query parameter to another name, such as file_format.

@johnthagen Think I'm facing the same issue (DRF + Viewset)

/api/?format=json works perfectly fine and returns results
/api/?format=datatables gives 404 error

Could you elaborate where you changed the query parameter name?

@wish7code what I found was that format used as a query parameter is consumed by DRF. If you want to have custom logic associated with a query parameter, you need to pick another query parameter name.

chidg commented

The format param determines the Renderer class by the content negotiator in rest_framework.negotiation.DefaultContentNegotiation.filter_renderers. If none of the available renderer classes match the given format, this method raises a Http404.

One way to fix this would be to override this filter_renderers method in order to use a default renderer class regardless of the format kwarg. Personally I didn't want to get too much into the weeds on this and just wanted to be able to use the 'format' query param to determine which serialiser to use, so I found a workaround by creating a custom renderer class.

from rest_framework.renderers import JSONRenderer

class GeoJsonRenderer(JSONRenderer):
    format = "geojson"

class MyViewSet(ModelPermissionsMixin, ModelViewSet):
    def get_renderers(self):
        return super().get_renderers() + [GeoJsonRenderer()]

    def get_serializer_class(self):
        format = self.request.query_params.get("format")
        if format and format == "geojson":
            return GeoJsonSerialiser
        return super().get_serializer_class()

This worked well.

It seems like the format kwarg is doing too much work here. For my purposes I just wanted it to determine which serialiser to use in my view - normal json or geojson. However, it's inbuilt purpose is tied up with content negotation and rendering, which are at a lower level and more technical than I would guess the average DRF user usually needs to get. I would suggest to the DRF maintainers that 'renderer' might be a more appropriate query parameter to use to determine the renderer class, rather than the more general 'format' which users may want to repurpose for other reasons.

Hi,
Why do you report the issue here ? It's not related to DRF-datatables (but DRF) or maybe I'm missing something ?

chidg commented

Hi @izimobil, correct, it's not related to this repository. This is a DRF issue. The reason I posted here is because my solution might help @davidhtien, and since I came across this issue page by googling the problem, it might help other people with the same problem. If you would prefer not to have this discussion here I will delete my post.

@chidg No, no problem :) It was just to clarify.