创建时向django-rest-framework ModelViewSet添加其他字段的最佳方法

时间:2013-09-02 10:36:28

标签: python django rest django-rest-framework

我有一个Book模型,其中包含一个外键给用户(该书的所有者):

class Book(models.Model):
    owner = models.ForiegnKey(User)
    ...

我为Book创建了一个ModelViewSet,它显示了登录用户拥有的书籍:

class BookViewSet(viewsets.ModelViewSet):
    model = Book
    serializer_class = BookSerializer
    def get_queryset(self):
        return Book.objects.filter(owner=self.request.user)

现在要创建一本新书,我想用request.user保存用户字段,而不是从其他客户端发送数据(为了更高的安全性)。例如:

def create(self, request, *args, **kwargs):
    request.DATA['user'] = request.user
    ... (some code to create new Book from request.DATA using serialize class)

但是我收到了这个错误: 此QueryDict实例是不可变的。 (表示request.DATA是一个不可变的QueryDict,无法更改)

在使用django rest framework创建对象时,您是否知道添加其他字段的更好方法?

3 个答案:

答案 0 :(得分:11)

更新:从v3开始,您需要执行此操作:

def perform_create(self, serializer):
    serializer.save(owner=self.request.user)

原则保持不变。


您希望将图书序列化程序的owner字段设为只读,然后在pre_save()中设置与用户的关联。

类似的东西:

def pre_save(self, obj):
    obj.owner = self.request.user

请参阅tutorial section on "Associating Snippets with Users"

我希望有所帮助。

答案 1 :(得分:7)

Django REST Framework 3中,它的价值发生了变化。现在有perform_create()替换了之前答案中建议的旧pre_save()post_save()挂钩。例如:

from rest_framework import viewsets

class MyViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

希望这能节省一些时间。

答案 2 :(得分:1)

如果您正在使用ModelSerializer,那么就像实施restore_object()方法一样简单:

class MySerializer(serializers.ModelSerializer):

    def restore_object(self, attrs, instance=None):

        create = not instance
        instance = super(MySerializer, self).restore_object(attrs, instance)

        if create:
            instance.user = self.context['request'].user

        return instance

    # ...

restore_object()用于将属性字典反序列化为对象实例。 ModelSerializer implements this method并为您在Meta类中指定的模型创建/更新实例。如果给定的instanceNone,则表示仍然需要创建对象。在这种情况下,您只需将user字段设置为所需的值。

更多信息: http://www.django-rest-framework.org/api-guide/serializers#declaring-serializers