英文:
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 
keywordsas 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 
keywordsas 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.
 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论