him*_*229 14 django django-serializer django-rest-framework
考虑这种情况,我有一个Book和Author模型.
serializers.py
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = models.Author
fields = ('id', 'name')
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True)
class Meta:
model = models.Book
fields = ('id', 'title', 'author')
Run Code Online (Sandbox Code Playgroud)
viewsets.py
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
Run Code Online (Sandbox Code Playgroud)
如果我发送GET书籍请求,这很有用.我得到一个带有嵌套序列化程序的输出,其中包含书籍详细信息和嵌套作者详细信息,这就是我想要的.
然而,当我要创建/更新的一本书,我要送一POST/ PUT/ PATCH与作者而不只是它们的ID的嵌套的细节.我希望能够通过指定作者ID而不是整个作者对象来创建/更新书籍对象.
所以,我的序列化器看起来像这样的GET请求
class BookSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True)
class Meta:
model = models.Book
fields = ('id', 'title', 'author')
Run Code Online (Sandbox Code Playgroud)
和我的串行器看起来像这样的POST,PUT,PATCH请求
class BookSerializer(serializers.ModelSerializer):
author = PrimaryKeyRelatedField(queryset=Author.objects.all())
class Meta:
model = models.Book
fields = ('id', 'title', 'author')
Run Code Online (Sandbox Code Playgroud)
我也不想为每种类型的请求创建两个完全独立的序列化器.我想修改一下该author字段BookSerializer.
最后,是否有更好的方法来完成这一切?
恕我直言,多个序列化器只会产生越来越多的混乱.
相反,我更喜欢以下解决方案:
我认为这是最干净的方法.
在DRF中查看我的类似问题和解决方案:允许GET请求中的所有字段,但将POST限制为仅一个字段
DRF的一个功能是您可以动态更改序列化器上的字段http://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields
我的用例:在GET上使用slug字段,这样我们就可以看到很好的关系代表,但是在POST/PUT上切换回经典的主键更新.将序列化器调整为以下内容:
class FooSerializer(serializers.ModelSerializer):
bar = serializers.SlugRelatedField(slug_field='baz', queryset=models.Bar.objects.all())
class Meta:
model = models.Foo
fields = '__all__'
def __init__(self, *args, **kwargs):
super(FooSerializer, self).__init__(*args, **kwargs)
try:
if self.context['request'].method in ['POST', 'PUT']:
self.fields['bar'] = serializers.PrimaryKeyRelatedField(queryset=models.Bar.objects.all())
except KeyError:
pass
Run Code Online (Sandbox Code Playgroud)
KeyError有时会在没有请求的情况下抛出代码初始化,可能是单元测试.
享受并负责任地使用.
您正在寻找get_serializer_class上的方法ViewSet。这允许您切换要使用的序列化器的请求类型。
from rest_framework import viewsets
class MyModelViewSet(viewsets.ModelViewSet):
model = MyModel
queryset = MyModel.objects.all()
def get_serializer_class(self):
if self.action in ('create', 'update', 'partial_update'):
return MySerializerWithPrimaryKeysForCreatingOrUpdating
else:
return MySerializerWithNestedData
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11858 次 |
| 最近记录: |