Huz*_*yed 5 django django-rest-framework
serializers.py
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = [
'popularity',
'director',
'genre',
'imdb_score',
'name',
]
Run Code Online (Sandbox Code Playgroud)
views.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)
Run Code Online (Sandbox Code Playgroud)
我这样发送数据,它可以正常工作。
{
"popularity": 83.0,
"director": "Victor Fleming",
"genre": [
1,
2,
3,
4
],
"imdb_score": 8.3,
"name": "The Wizard of Oz"
}
Run Code Online (Sandbox Code Playgroud)
但是我想像这样发送数据:
{
"popularity": 83.0,
"director": "Victor Fleming",
"genre": [
"Adventure",
"Family",
"Fantasy",
"Musical"
],
"imdb_score": 8.3,
"name": "The Wizard of Oz"
}
Run Code Online (Sandbox Code Playgroud)
请参阅流派列表-我要发送的不是主键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)
Run Code Online (Sandbox Code Playgroud)
即使我列出数据或获取数据,它也应该发送流派名称而不是ID。我尝试使用StringRelatedField,但这给了我错误。
必须实现/ api / movie / StringRelatedField.to_internal_value()处的NotImplementedError。
cez*_*zar 12
假设你StringRelatedField在你MovieSerializer这样使用:
class MovieSerializer(serializers.ModelSerializer):
genre = serializers.StringRelatedField(many=True)
class Meta:
model = Movie
fields = [
'popularity',
'director',
'genre',
'imdb_score',
'name',
]
Run Code Online (Sandbox Code Playgroud)
检索电影列表时,结果如下所示:
[
{
"popularity": 83.0,
"director": "Victor Fleming",
"genre": [
"Adventure",
"Family",
"Fantasy",
"Musical"
],
"imdb_score": 8.3,
"name": "The Wizard of Oz"
}
]
Run Code Online (Sandbox Code Playgroud)
但是如果你想创建一部新电影,那么它就行不通了,因为它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',
)
Run Code Online (Sandbox Code Playgroud)
这是一个可以通过多种方式高度定制的简单示例。
该方法display_value定义了对象流派的显示方式,例如在表单中。这里它只返回对象 Genre ,即__str__.
该方法to_representation定义了对象 Genre 在输出(JSON 或 XML)中的显示方式。它与前面的方法非常相似,但在这里我们必须明确地将 Genre 转换为字符串。当然,您可以根据您的要求创建更复杂的输出。
该方法to_internal_value通过获取给定值的对象类型来解决您的实际问题。如果这里有更复杂的方法to_representation,则需要扩展逻辑来获取适当的对象。
使用这种方法,您可以以您想要的形式发布 JSON,指定流派名称而不是它们的 id。
我希望这个例子也能帮助其他人。
如下重写create()序列化器的方法,
class MovieSerializer(serializers.ModelSerializer):
genre = serializers.ListSerializer(child=serializers.CharField())
class Meta:
model = Movie
fields = [
'popularity',
'director',
'genre',
'imdb_score',
'name',
]
def create(self, validated_data):
genre = validated_data.pop('genre',[])
movie = super().create(validated_data)
genre_qs = Genre.objects.filter(name__in=genre)
movie.genre.add(*genre_qs)
return movieRun Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1426 次 |
| 最近记录: |