2

We've developed a responsive map using this tutorial where Django Rest Framework serves responses that populates the map. My viewsets.py:

class MarkerViewSet(viewsets.ReadOnlyModelViewSet):
    """Marker view set."""

    bbox_filter_field = "geom"
    filter_backends = (filters.InBBoxFilter,)
    queryset = Tablename.objects.all()
    serializer_class = MarkerSerializer
    pagination_class = GeoPaginator

I'd like to add optional criteria to this filter if they are found in a GET value. The rest of my project uses views.py, which filters things differently. My simplified views.py which does this for something else:

def EgFilterView(request):
    qs = Tablename.objects.all()
    date_min_query = request.GET.get('dmin')

    min_date = 1970

    qs = qs.filter(date__gte=dt.datetime(int(date_min_query), 1, 1, tzinfo=pytz.UTC))

    context = {
        'queryset': qs,
        'dmin': min_date,
    }

    return render(request, "main_page.html", context)

But it looks like viewsets.py doesn't handle .get() values in this way, but instead uses .list() and .create(), which I don't understand.

How can I include additional filters into my viewsets.py to further filter things with GET values? Would it be better to attempt to convert this viewsets.py / other complicated API stuff I don't understand into views.py?

1 Answers1

0

Figured it out through other SO threads and the help of kind people over in the Django Forums.

We first need to make the request include the GET values. If following this tutorial where the request URL is constructed in JS through:

const markers_url = `/api/markers/?in_bbox=${map.getBounds().toBBoxString()}`

We need to add a string of the other inputs and their values:

const form = document.querySelector('#theForm'); // supply ID of form containing inputs
var object = Object.values(form).reduce((obj,field) => { obj[field.name] = field.value; return obj }, {});  // get an object of all inputs and values https://stackoverflow.com/a/47188324
delete object[""]; // remove empty string we couldn't figure out cause of
const markers_url = `/api/markers/?in_bbox=${map.getBounds().toBBoxString()}` + '&' + new URLSearchParams(object).toString() // make this object a string in URLSearchParams format and suffix to url

Now we need to make viewsets.py filter the queryset with these GET values. We can do this by overriding the filter_queryset(self, queryset) method:

class MarkerViewSet(viewsets.ReadOnlyModelViewSet):
    """Marker view set."""
    bbox_filter_field = "geom"
    filter_backends = (filters.InBBoxFilter,)
    queryset = Tablename.objects.all()

    def filter_queryset(self, queryset):
        queryset = super().filter_queryset(queryset)
        extra_field1 = self.request.query_params.get('extra_field1') # creates string of the GET param "extra_field1"
        if extra_field1:
            queryset = queryset.filter(extra_field1=extra_field1) # filter here as desired
        return queryset

    serializer_class = MarkerSerializer
    pagination_class = GeoPaginator