11

我有一个 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 框架创建对象时,您知道添加其他字段的更好方法吗?

4

3 回答 3

16

更新:从 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

请参阅“将片段与用户关联”的教程部分

我希望这会有所帮助。

于 2013-09-02T10:54:53.977 回答
8

值得一提的是,这在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)

希望这可以节省一些时间。

于 2015-02-18T23:37:29.630 回答
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 实现此方法Meta并为您在类中指定的模型创建/更新实例。如果给定instance的是None,则意味着仍然必须创建对象。在这种情况下,您只需将user字段设置为所需的值。

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

于 2014-04-28T10:03:13.177 回答