英文:
How to return a list of objects using a Django REST API post request?
问题
我是新手使用REST API,尝试创建一个API,可以进行POST请求,包含关键字,然后返回与该关键字相关的文章列表。
无法使用GET请求的原因是因为我不是从数据库中获取任何内容,我是基于POST请求中的关键字创建文章列表。
Views.py:
def article_get(request):
if request.method == 'POST':
serializer = serializers.ArticleListSerializer(data=request.data)
if serializer.is valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
classes.py:
class Article:
title = ""
url = ""
def __init__(self, url, title):
self.title = title
self.url = url
class ArticleList:
keywords = ""
articles = []
def __init__(self, keywords, articles):
self.keywords = keywords
self.articles = articles
self.articles.append(serializedArticle)
self.articles.append(serializedArticle)
行将一个序列化的文章附加到文章列表,我希望这只会将以JSON格式表示的文章添加到文章列表,但实际上产生了以下错误:类型为ArticleSerializer的对象无法进行JSON序列化
。
serializers.py:
class ArticleSerializer(serializers.Serializer):
title = serializers.CharField(max_length=300)
url = serializers.CharField(max_length=300)
def create(self, validated_data):
return classes.Article(**validated_data)
class ArticleListSerializer(serializers.Serializer):
articles = serializers.ListField()
keywords = serializers.CharField(max_length=100)
def create(self, validated_data):
return classes.ArticleList(**validated_data)
正如我提到的,我远非API专家。我希望通过将序列化的Article对象附加到ArticleList中,它能够返回响应中的ArticleList,但它不能。
有人知道如何修复这个问题吗?或者:有人知道我是否走在正确的道路上吗?我很难理解Django REST API文档,所以我认为我很可能犯了一些愚蠢的错误。所以,任何反馈都非常感激。
英文:
I am new to using REST API's and am trying to create an API where I can make a POST request containing keywords, which should then return a list of articles related to that keyword.
The reason I can't use a GET request is because I am not GETting anything from a database, I am creating the list of articles based on the keyword from the POST request.
Views.py:
def article_get(request):
if request.method == 'POST':
serializer = serializers.ArticleListSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
classes.py:
class Article:
title = ""
url = ""
def __init__(self, url, title):
self.title = title
self.url = url
class ArticleList:
keywords = ""
articles = []
def __init__(self, keywords, articles):
self.keywords = keywords
self.articles = articles
self.articles.append(serializedArticle)
The self.articles.append(serializedArticle)
line appends a serialized article to the articles list,
which I hoped would simply add an article in JSON format to the articlelist, but instead it produces the following error:
Object of type ArticleSerializer is not JSON serializable
serializers.py:
class ArticleSerializer(serializers.Serializer):
title = serializers.CharField(max_length=300)
url = serializers.CharField(max_length=300)
def create(self, validated_data):
return classes.Article(**validated_data)
class ArticleListSerializer(serializers.Serializer):
articles = serializers.ListField()
keywords = serializers.CharField(max_length=100)
def create(self, validated_data):
return classes.ArticleList(**validated_data)
As I mentioned, I am FAR from being an API expert. I had hoped that by appending a serialized Article object to the ArticleList, that it would be able to return the ArticleList in the response, but it can't.
Does anyone know how to fix this? Or: does anyone know if I'm even on the right track? I'm struggling to understand the django REST API documentation so I reckon there's a big chance I'm making some dumb mistakes. So: any feedback is greatly appreciated.
答案1
得分: 0
以下是您要翻译的内容:
In order to retrieve or filter data you need to store it somewhere. Not necessarily a database. It can be in memory, for instance:
database.py
```python
database = {
"articles":
[
{
"title": "Prepopulated Article",
"url": "http://prepopulated.example.com",
"keywords": ["prepopulated", "stuff"]
}
],
}
serializers.py
class ArticleSerializer(serializers.Serializer):
title = serializers.CharField()
url = serializers.URLField()
keywords = serializers.ListField()
views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from myapp.api.serializers import ArticleSerializer
from myapp.database import database
@api_view(['POST'])
def article_create(request):
""" Endpoint for creating articles """
if request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
database['articles'].append(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@api_view(['GET', 'POST'])
def article_list(request):
""" Endpoint for listing Articles """
if request.method == 'POST':
data = []
keywords = request.data.pop('keywords', None)
# Would be equivalent to filtering a QuerySet
if keywords and isinstance(keywords, list):
for key in keywords:
for obj in database['articles']:
if key in obj['keywords'] and obj not in data:
data.append(obj)
serializer = ArticleSerializer(data=data, many=True)
if serializer is_valid(raise_exception=True):
return Response(serializer.data, status=status.HTTP_200_OK)
else:
print(database['articles'])
serializer = ArticleSerializer(data=database['articles'], many=True)
if serializer.is_valid(raise_exception=True):
return Response(serializer.data, status=status.HTTP_200_OK)
If we send the following payload to create endpoint:
{
"title": "Article One",
"url": "http://article-one.example.com",
"keywords": ["new", "stuff"]
}
And this payload to list
endpoint. Then it returns the new created article:
{
"keywords": ["new"]
}
Whereas the one below would return both articles.
{
"keywords": ["stuff"]
}
A few notes:
- Using
keywords
as a list to improve the filtering (instead of string). - The pseudo-database will reset every time you reload the server. So objects you create using the endpoint will be deleted.
<details>
<summary>英文:</summary>
In order to retrieve or filter data you need to store it somewhere. Not necessarily a database. It can be in memory, for instance:
database.py
```python
database = {
"articles":
[
{
"title": "Prepopulated Article",
"url": "http://prepropulated.example.com",
"keywords": ["prepopulated", "stuff"]
}
],
}
serializers.py
class ArticleSerializer(serializers.Serializer):
title = serializers.CharField()
url = serializers.URLField()
keywords = serializers.ListField()
views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from myapp.api.serializers import ArticleSerializer
from myapp.database import database
@api_view(['POST'])
def article_create(request):
""" Endpoint for creating articles """
if request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
database['articles'].append(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@api_view(['GET', 'POST'])
def article_list(request):
""" Endpoint for listing Articles """
if request.method == 'POST':
data = []
keywords = request.data.pop('keywords', None)
# Would be equivalent to filtering a QuerySet
if keywords and isinstance(keywords, list):
for key in keywords:
for obj in database['articles']:
if key in obj['keywords'] and obj not in data:
data.append(obj)
serializer = ArticleSerializer(data=data, many=True)
if serializer.is_valid(raise_exception=True):
return Response(serializer.data, status=status.HTTP_200_OK)
else:
print(database['articles'])
serializer = ArticleSerializer(data=database['articles'], many=True)
if serializer.is_valid(raise_exception=True):
return Response(serializer.data, status=status.HTTP_200_OK)
If we send the following payload to create endpoint:
{
"title": "Article One",
"url": "http://article-one.example.com",
"keywords": ["new", "stuff"]
}
And this payload to list
endpoint. Then it returns the new created article:
{
"keywords": ["new"]
}
Whereas the one below would return both articles.
{
"keywords": ["stuff"]
}
A few notes:
- Using
keywords
as a list to improve the filtering (instead of string). - The pseudo-database will reset every time you reload the server. So objects you create using the endpoint will be deleted.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论