我正在尝试制作网络应用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)
答案 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