Complex aggregation methods as single param in query string
<p>Iâm trying to design a flexible API with django REST. What I meant by this is to have basically any field filterable through a query string and in addition to that have a param in the query string that can denote some complex method to perform. Ok, here are the details:</p>

<p><strong>views.py</strong></p>

<pre><code>class StarsModelList(generics.ListAPIView):
    queryset = StarsModel.objects.all()
    serializer_class = StarsModelSerializer
    filter_class = StarsModelFilter
</code></pre>

<p><strong>serializers.py</strong></p>

<pre><code>class StarsModelSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = StarsModel
        fields = '__all__'
</code></pre>

<p><strong>mixins.py</strong></p>

<pre><code>class DynamicFieldsMixin(object):
    def __init__(self, *args, **kwargs):
        super(DynamicFieldsMixin, self).__init__(*args, **kwargs)
        fields = self.context['request'].query_params.get('fields')
        if fields:
            fields = fields.split(',')
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields.keys())
            for field_name in existing - allowed:
                self.fields.pop(field_name)
</code></pre>

<p><strong>filters.py</strong></p>

<pre><code>class CSVFilter(django_filters.Filter):
    def filter(self, qs, value):
        return super(CSVFilter, self).filter(qs, django_filters.fields.Lookup(value.split(u","), "in"))


class StarsModelFilter(django_filters.FilterSet):
    id = CSVFilter(name='id')

    class Meta:
        model = StarsModel
        fields = ['id',]
</code></pre>

<p><strong>urls.py</strong></p>

<pre><code>url(râ^/stars/$â, StarsModelList.as_view())
</code></pre>

<p>this give me the ability to construct query strings like so:</p>

<pre><code>/api/stars/?id=1,2,3&amp;fields=type,age,magnetic_field,mass
</code></pre>

<p>this is great I like this functionality, but there are also many custom aggregation/transformation methods that need to be applied to this data. What I would like to do is have an agg= param like so: </p>

<pre><code>/api/stars/?id=1,2,3&amp;fields=type,age,magnetic_field,mass,&amp;agg=complex_method
</code></pre>

<p>or just:</p>

<pre><code>/api/stars/?agg=complex_method
</code></pre>

<p>where defining the complex_method grabs the correct fields for the job.</p>

<p>Iâm not exactly sure where to start and where to add the complex methods so I would really appreciate some guidance. I should also note the api is only for private use supporting a django application, its not exposed to the public.</p>

<p>Definitely would be good to see your MyModelList class but anyway my example as per <a href="https://docs.djangoproject.com/en/1.10/ref/class-based-views/base/" rel="nofollow">https://docs.djangoproject.com/en/1.10/ref/class-based-views/base/</a></p>

<pre><code>from django.http import HttpResponse
from django.views import View

class StarsModelList(generics.ListAPIView):
    queryset = StarsModel.objects.all()
    serializer_class = StarsModelSerializer
    filter_class = StarsModelFilter

    def complex_method(request):
        # do smth to input parameters if any
        return HttpResponse('Hello, World!')

    def get(self, request, *args, **kwargs):
        if request.GET.get('agg', None) == 'complex_method':
           return self.complex_method(request)
        return HttpResponse('Hi, World!')
</code></pre>

python django django-rest-framework