从Django REST框架API请求多个ID

时间:2015-09-30 21:56:30

标签: python django django-models django-rest-framework

我正在尝试制作网络应用API。我想提出一个API请求,可以提交多个ID。

django rest framework tutorial显示了如何从模型中获取所有记录。例如,http://127.0.0.1:8000/snippets/将返回所有代码段记录。本教程还介绍了如何从模型中检索单个项目。 http://127.0.0.1:8000/snippets/2/只返回pk = 2的代码段记录。

我希望能够请求多条记录,但不是所有记录。

如何更改此代码,以便我可以请求多个代码段?

代码段/ urls.py

from django.conf.urls import url
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

代码段/ views.py

def snippet_detail(request, *pk):
    try:
        snippet = Snippet.objects.filter(pk__in=pk)
    except Snippet.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return JSONResponse(serializer.data)

7 个答案:

答案 0 :(得分:10)

根据您的评论,您可以通过网址发送ID:

127.0.0.1:8000/snippets/?ids=2,3,4

并在您的视图中

...
ids = request.GET.get('ids')  # u'2,3,4' <- this is unicode
ids = ids.split(',')  # [u'2',u'3',u'4'] <- this is a list of unicodes with ids values

然后您可以查询Snippet模型:

Snippet.objects.filter(pk__in=ids)

如果url中的ID之间有空格,这可能会给你带来一些问题:

127.0.0.1:8000/snippets/?ids=2, 3 , 4

在执行查询之前,您可能需要处理每个值

答案 1 :(得分:4)

我发现这可以工作,遵循Django REST Framework主教程,然后是Filtering against query parameters上的文档,稍微适应。这允许单个url从两个GET请求返回数据:一个返回对象,其id与作为参数给出的id匹配,另一个返回所有对象,如果没有提供参数。

代码段/ urls.py

.... 
from snippet.serializers import SnippetSerializer
....

class SnippetList(generics.ListCreateAPIView):
    serializer_class = SnippetSerializer

    def get_queryset(self):

        # Get URL parameter as a string, if exists 
        ids = self.request.query_params.get('ids', None)

        # Get snippets for ids if they exist
        if ids is not None:
            # Convert parameter string to list of integers
            ids = [ int(x) for x in ids.split(',') ]
            # Get objects for all parameter ids 
            queryset = Product.objects.filter(pk__in=ids)

        else:
            # Else no parameters, return all objects
            queryset = Product.objects.all()

        return queryset

代码段/ views.py

....
class SnippetSerializer(serializers.ModelSerializer):

    class Meta:
        model = Snippet
        fields = ('url', 'id', 'title', 'code', 'linenos', 'language', 'style')

代码段/ serializers.py

SqlQuery

答案 2 :(得分:3)

一种可能的方法是将pk(s)的lis作为GET请求数据发送,如下所示:

  • 向&#34; / snippets&#34;

  • 获取请求
  • 请求正文:{&#34; list_of_pk&#34;:[1,2,3 ...]}

然后:

代码段/ urls.py

from django.conf.urls import url
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

代码段/ views.py

def snippet_list(request):
    if request.method == 'GET':
        pk_list = request.GET.get('list_of_pk')
        if pk_list:
            snippets = Snippet.objects.filter(pk__in=pk_list)
        else:
            snippets = Snippet.objects.all()
        #the serialization...

答案 3 :(得分:2)

这是我最终的目标:

没有变化 代码段/ urls.py

from django.conf.urls import url
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

收到

http://127.0.0.1:8000/snippets/?ids=2,3,4

段/ views.py

from rest_framework.decorators import api_view

@api_view(['GET', 'POST'])    
def snippet_list(request):
    if request.method == 'GET':
        ids = request.query_params.get('ids')  # u'2,3,4' <- this is unicode
        ids = ids.split(',')
        snippets = Snippet.objects.filter(pk__in=ids)
        serializer = SnippetSerializer(snippet, many=True)
        return JSONResponse(serializer.data)

答案 4 :(得分:0)

  

虽然没有明确的标准,但是大多数Web框架都允许将多个值与单个字段相关联(例如field1 = value1&field1 = value2&field2 = value3)。

Django也支持此功能。 要获取值列表,可以使用:' Search for "Project Code CSO" For Each Rng In Range("a1:fi1") If Rng = "Project Code CSO" Then f_1 = Rng.Column End If Next Columns(f_1).Copy Destination:=Sheets(7).Columns("A") ' Search for "Code" For Each Rng In Range("a1:fi1") If Rng = "Code" Then f_2 = Rng.Column End If Next Columns(f_2).Copy Destination:=Sheets(7).Columns("B") ' Search for "Study Desc" For Each Rng In Range("a1:fi1") If Rng = "Study Desc" Then f_3 = Rng.Column End If Next Columns(f_3).Copy Destination:=Sheets(7).Columns("C") ' Search for "Study Phase" For Each Rng In Range("a1:fi1") If Rng = "Study Phase" Then f_4 = Rng.Column End If Next Columns(f_4).Copy Destination:=Sheets(7).Columns("D") ' Search for "Regions/countries List" For Each Rng In Range("a1:fi1") If Rng = "Regions/countries List" Then f_5 = Rng.Column End If Next Columns(f_5).Copy Destination:=Sheets(7).Columns("E") ' Search for "? RTM Study" For Each Rng In Range("a1:fi1") If Rng = "? RTM Study" Then f_6 = Rng.Column End If Next Columns(f_6).Copy Destination:=Sheets(7).Columns("F") ' Search for "Cent." For Each Rng In Range("a1:fi1") If Rng = "Cent." Then f_7 = Rng.Column End If Next Columns(f_7).Copy Destination:=Sheets(7).Columns("G") ' Search for "Pat." For Each Rng In Range("a1:fi1") If Rng = "Pat." Then f_8 = Rng.Column End If Next Columns(f_8).Copy Destination:=Sheets(7).Columns("H") ' Search for "Pat/Cent" For Each Rng In Range("a1:fi1") If Rng = "Pat/Cent" Then f_9 = Rng.Column End If Next Columns(f_9).Copy Destination:=Sheets(7).Columns("I") ' Search for "FPI Planned Start" For Each Rng In Range("a1:fi1") If Rng = "FPI Planned Start" Then f_10 = Rng.Column End If Next Columns(f_10).Copy Destination:=Sheets(7).Columns("J") ' Search for "LPI/LSI planned Date" For Each Rng In Range("a1:fi1") If Rng = "LPI/LSI planned Date" Then f_11 = Rng.Column End If Next Columns(f_11).Copy Destination:=Sheets(7).Columns("K") ' Search for "LPLV/LSLV planned start date" For Each Rng In Range("a1:fi1") If Rng = "LPLV/LSLV planned start date" Then f_12 = Rng.Column End If Next Columns(f_12).Copy Destination:=Sheets(7).Columns("L") ' Search for "DBL-FPI" For Each Rng In Range("a1:fi1") If Rng = "DBL-FPI" Then f_13 = Rng.Column End If Next Columns(f_13).Copy Destination:=Sheets(7).Columns("M") ' Search for "DBL planned start" For Each Rng In Range("a1:fi1") If Rng = "DBL planned start" Then f_14 = Rng.Column End If Next Columns(f_14).Copy Destination:=Sheets(7).Columns("N") Sheets(7).Select ids = request.GET.getlist('ids')文档的更多示例:

MultiValueDict

答案 5 :(得分:0)

您可以安装django-filter,我相信它是drf https://django-filter.readthedocs.io/en/master/随附的

您还可以将其设置为过滤器,并避免在视图集上使用get_queryset方法

给出此请求

/api/snippets/?ids=1,2,3,4

然后编写Django过滤器集和方法

import django_filters


def filter_by_ids(queryset, name, value):
    values = value.split(',')
    return queryset.filter(id__in=values)


class SnippetFilterSet(django_filters.FilterSet):
   ids = django_filters.CharFilter(method=filter_by_ids)

   class Meta:
      model = Snippet
      fields = ['ids']

然后在您的ModelViewSet中

from rest_framework.viewsets import ModelViewSet
from app.snippets.models import Snippet
from app.snippets.filters import SnippetFilterSet # path to filterset

class SnippetView(ModelViewSet):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    filterset_class = SnippetFilterSet

答案 6 :(得分:0)

django-filter 文档给出了一个很好的例子:this Microsoft Doc

对于您的情况:

class SnippetFilterSet(BaseInFilter, NumberFilter):
    pass

class F(FilterSet):
    ids = NumberInFilter(field_name='id', lookup_expr='in')

    class Meta:
        model = Snippet