gpt4 book ai didi

django - 在 Django REST Framework 中,代替主键发送不同的字段

转载 作者:行者123 更新时间:2023-12-04 10:06:28 27 4
gpt4 key购买 nike

序列化程序.py

class MovieSerializer(serializers.ModelSerializer):

class Meta:
model = Movie
fields = [
'popularity',
'director',
'genre',
'imdb_score',
'name',
]

View .py
class MovieList(generics.ListCreateAPIView):
queryset = Movie.objects.all().order_by('-id')[:10]
serializer_class = MovieSerializer
permission_classes = (IsAuthenticated,)

def list(self, request):
queryset = self.get_queryset()
serializer = MovieSerializer(queryset, many=True)
return Response(serializer.data)

def post(self, request, format=None):
data = request.data
if isinstance(data, list):
serializer = self.get_serializer(data=request.data, many=True)
else:
serializer = self.get_serializer(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)

我像这样发送我的数据并且它工作正常。
{
"popularity": 83.0,
"director": "Victor Fleming",
"genre": [
1,
2,
3,
4
],
"imdb_score": 8.3,
"name": "The Wizard of Oz"
}

但我想像这样发送数据:
{
"popularity": 83.0,
"director": "Victor Fleming",
"genre": [
"Adventure",
"Family",
"Fantasy",
"Musical"
],
"imdb_score": 8.3,
"name": "The Wizard of Oz"
}

查看流派列表 - 我发送的不是主键 name .

这些是我的模型:
class Genre(models.Model):
name = models.CharField(max_length=30, unique=True) # make unique

def __str__(self):
return self.name

class Movie(models.Model):
popularity = models.FloatField(max_length=10)
director = models.CharField(max_length=30)
genre = models.ManyToManyField(Genre)
imdb_score = models.FloatField(max_length=10)
name = models.CharField(max_length=30)

即使当我列出数据或获取数据时,它也应该发送流派名称而不是 id。我尝试使用 StringRelatedField ,但它给了我错误。

NotImplementedError at /api/movie/ StringRelatedField.to_internal_value() must be implemented.

最佳答案

假设您使用了 StringRelatedField在您的 MovieSerializer像这样:

class MovieSerializer(serializers.ModelSerializer):
genre = serializers.StringRelatedField(many=True)

class Meta:
model = Movie
fields = [
'popularity',
'director',
'genre',
'imdb_score',
'name',
]

检索电影列表时,结果如下所示:
[
{
"popularity": 83.0,
"director": "Victor Fleming",
"genre": [
"Adventure",
"Family",
"Fantasy",
"Musical"
],
"imdb_score": 8.3,
"name": "The Wizard of Oz"
}
]

但是如果你想制作一部新电影,那么它就行不通了,因为 StringRelatedField是只读的。

但是,您可以创建自定义相关字段。

这是完整的 serializers.py :
from rest_framework import serializers

from .models import Genre, Movie


class GenreRelatedField(serializers.RelatedField):
def display_value(self, instance):
return instance

def to_representation(self, value):
return str(value)

def to_internal_value(self, data):
return Genre.objects.get(name=data)


class MovieSerializer(serializers.ModelSerializer):
genre = GenreRelatedField(
queryset=Genre.objects.all(),
many=True
)

class Meta:
model = Movie
fields = (
'popularity',
'director',
'genre',
'imdb_score',
'name',
)

这是一个可以通过多种方式高度定制的简单示例。

方法 display_value定义对象流派的显示方式,例如在表单中。这里它只返回对象 Genre,即 __str__ 的输出.

方法 to_representation定义对象流派在输出(JSON 或 XML)中的显示方式。它与前面的方法非常相似,但在这里我们必须明确地将 Genre 转换为字符串。当然,您可以根据您的要求创建更复杂的输出。

方法 to_internal_value通过获取给定值的对象类型来解决您的实际问题。如果您有更复杂的方法 to_representation在这里,您需要扩展逻辑来获取适当的对象。

使用这种方法,您可以以您想要的形式发布 JSON,指定流派名称而不是它们的 id。

我希望这个例子也能帮助其他人。

关于django - 在 Django REST Framework 中,代替主键发送不同的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55161052/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com