复杂聚合方法作为查询字符串中的单个参数

时间:2016-09-07 13:49:46

标签: python django django-rest-framework

我正在尝试使用django REST设计灵活的API。我的意思是基本上可以通过查询字符串过滤任何字段,除此之外在查询字符串中有一个可以表示要执行的复杂方法的参数。好的,详情如下:

views.py

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

serializers.py

class StarsModelSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = StarsModel
        fields = '__all__'

mixins.py

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)

filters.py

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',]

urls.py

url(r’^/stars/$’, StarsModelList.as_view())

这使我能够构建如下的查询字符串:

/api/stars/?id=1,2,3&fields=type,age,magnetic_field,mass

这很棒我喜欢这个功能,但是还有许多需要应用于此数据的自定义聚合/转换方法。我想做的是像这样有一个agg = param:

/api/stars/?id=1,2,3&fields=type,age,magnetic_field,mass,&agg=complex_method

或只是:

/api/stars/?agg=complex_method

定义complex_method会抓取作业的正确字段。

我不确定从哪里开始以及在哪里添加复杂的方法,所以我真的很感激一些指导。我还应该注意,api仅供私人使用,支持django应用程序,不会向公众开放。

1 个答案:

答案 0 :(得分:1)

绝对会很高兴看到你的MyModelList类,但无论如何我的例子都是https://docs.djangoproject.com/en/1.10/ref/class-based-views/base/

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!')