英文:
Make endpoint that returns a list of strings using Django Rest Framework
问题
我有这个艺术家模型:
class Artist(models.Model):
name = models.CharField(max_length=100)
#songs = models.ManyToManyField('Song', related_name='artists')
def __str__(self):
return self.name
class Meta:
ordering = ('name',)
我想创建一个 API 端点,将所有艺术家的名称作为字符串列表返回,例如:["50 Cent", "Eminem", "Snoop Dogg", ...]。我在我的 urls.py 中创建了这个 artists/names/
URL:
path('artists/names/', views.artist_names, name='artist_names'),
我已经尝试了两种方法:
- 使用 Python 列表:
@api_view(['GET'])
def artist_names(request):
artists = Artist.objects.values_list('name', flat=True)
artist_names_list = list(artists)
return Response(artist_names_list)
- 在我的 serializers.py 中使用 ListSerializer:
class ArtistNameSerializer(serializers.Serializer):
name = serializers.ListSerializer(child=serializers.CharField())
在我的 views.py 中,我创建了 artist_names 方法:
@api_view(['GET'])
def artist_names(request):
artists = Artist.objects.values_list('name', flat=True)
serializer = ArtistNameSerializer(artists, many=True)
return Response(serializer.data)
无论从哪种方法,当我访问该端点时,我都得到:
GET /api/artists/names/
HTTP 404 Not Found
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"detail": "Not found."
}
有人可以帮助吗?我做错了什么?
英文:
I have this Artist model:
class Artist(models.Model):
name = models.CharField(max_length=100)
#songs = models.ManyToManyField('Song', related_name='artists')
def __str__(self):
return self.name
class Meta:
ordering = ('name',)
I want to make a api endpoint that returns all the Artists row names as a list of string like for example: ["50 Cent", "Eminem", "Snoop Dogg", ...] . i have created this artists/names/
url in my urls.py:
path('artists/names/', views.artist_names, name='artist_names'),
I have tried two ways already:
- Using a python list:
@api_view(['GET'])
def artist_names(request):
artists = Artist.objects.values_list('name', flat=True)
artist_names_list = list(artists)
return Response(artist_names_list)
- Using ListSerializer in my serializers.py:
class ArtistNameSerializer(serializers.Serializer):
name = serializers.ListSerializer(child=serializers.CharField())
and in my views.py i created the artist_names method:
@api_view(['GET'])
def artist_names(request):
artists = Artist.objects.values_list('name', flat=True)
serializer = ArtistNameSerializer(artists, many=True)
return Response(serializer.data)
From both of them when i go to the endpoint i get:
GET /api/artists/names/
HTTP 404 Not Found
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"detail": "Not found."
}
Can someone help? What am i doing wrong?
答案1
得分: 0
我想你对你的方法(1)可能会遇到的问题是,如果不先进行“序列化”,你的Python列表就不是有效的JSON,因此DRF无法正确处理它。
你的方法(2)基本正确,但你在你的“Serializer”类中使用了serializers.ListSerializer
,而应该使用serializers.ListField
。一旦更正了这一点,你的视图中也不需要使用many=True
。
以下是我让你的代码正常运行的方式:
serializers.py
from rest_framework import serializers
from .models import Artist
class ArtistSerializer(serializers.Serializer):
artists = Artist.objects.all()
names = serializers.ListField(
child=serializers.CharField(max_length=100),
default=artists
)
views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Artist
from .serializers import ArtistSerializer
@api_view(['GET'])
def artist_names(request):
artists = Artist.objects.all()
serializer = ArtistSerializer(artists)
return Response(serializer.data)
urls.py (在应用程序中)
from django.urls import path
from . import views
urlpatterns = [
path('artists/names/', views.artist_names, name='artist_names'),
]
models.py 文件与你的相同,项目级别的 urls.py 文件包含了 path('', include('app.urls')),
这一行,所以只需确保包含它,并将 app 更改为你的应用程序的名称。
这个代码给我产生的输出如下:
希望如果你进行上述调整(看起来主要是对你的序列化程序和视图文件的轻微更改),那么你应该会看到相同的输出!
英文:
I imagine the issue you would have with your method (1) is that without 'serializing' first, your Python list is not valid JSON, so won't be handled correctly by DRF.
Your method (2) is on the right track, but you are using a serializers.ListSerializer
inside your 'Serializer' class, where you should be putting a serializers.ListField
. You also don't need many=True
in your view once this is corrected.
The below is how I got your code working:
serializers.py
from rest_framework import serializers
from .models import Artist
class ArtistSerializer(serializers.Serializer):
artists = Artist.objects.all()
names = serializers.ListField(
child=serializers.CharField(max_length=100),
default=artists
)
views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Artist
from .serializers import ArtistSerializer
@api_view(['GET'])
def artist_names(request):
artists = Artist.objects.all()
serializer = ArtistSerializer(artists)
return Response(serializer.data)
urls.py (in app)
from django.urls import path
from . import views
urlpatterns = [
path('artists/names/', views.artist_names, name='artist_names'),
]
The models.py file is identical to yours, and the project-level urls.py file features the line path('', include('app.urls')),
, so just make sure to include that and change app to whatever name your app is.
The output this gave me is below:
Hopefully if you make the above adjustments (looks like they are mostly just the minor changes to your serializers and views files I outlined above) then you'll see the same output!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论