简体   繁体   English

Django-tastypie将request.user传递给自定义保存方法

[英]Django-tastypie pass request.user to custom save method

Since my model's custom save method takes request.user as an argument I'm unable to do POST/PUT requests. 由于我模型的自定义保存方法将request.user作为参数,因此我无法执行POST / PUT请求。

TypeError at /api/obsadmin/observation/23
save() takes at least 2 arguments (1 given)

I'm using SessionAuthentication() and have included the CSRF token. 我正在使用SessionAuthentication()并包含CSRF令牌。

Here's the relevant model part: 这是相关的模型部分:

def save(self, user, owner=None, *args, **kwargs):
    self.updated_by = user.id
    super(ObsModel, self).save(*args, **kwargs)

And the resource: 和资源:

class ObservationResource2(ModelResource):

comments = fields.ToManyField(CommentResource2, 'comments', full=True, null=True)

class Meta:
    queryset = Observation.objects.filter(is_verified=True)
    authentication = SessionAuthentication()
    authorization = DjangoAuthorization()
    resource_name = 'observation'
    always_return_data = True

I've just achieved this same end goal by using the built-in hydrate methods to modify the data prior to saving. 通过使用内置的hydrate方法在保存之前修改数据,我刚刚达到了相同的最终目标。 The current request is available in bundle.request inside the hydrate methods. hydrate方法中的bundle.request提供了当前请求。 See the docs here . 此处查看文档。

I have a Friend model exposed via FriendResource that I want to link to the creating Django user via a user ForeignKey field. 我有一个通过FriendResource公开的Friend模型,我想通过user ForeignKey字段链接到正在创建的Django用户。

My example Resource code: 我的示例资源代码:

class FriendResource(ModelResource):
    class Meta:
        queryset = Friend.objects.all()
        resource_name = 'friend'
        excludes = ['slug',]
        authentication = SessionAuthentication()
        authorization = DjangoAuthorization()
        always_return_data = True

    def get_object_list(self, request):
        return super(FriendResource, self).get_object_list(request).filter(user=request.user)

    def hydrate(self, bundle):
        bundle.obj.user = bundle.request.user
        return bundle

Hope that helps! 希望有帮助!

You could override the default save() method on your ModelResource subclass. 您可以在ModelResource子类上覆盖默认的save()方法。 Looking at the default implementation shows that save() is called with a bundle object which has both the request and the object to be saved. 查看默认实现会发现,使用捆绑对象调用save() ,该捆绑对象同时具有请求和要保存的对象。

Unfortunately, there's no easy way to change this without copying most of that code because changing a Django model's save() signature is fairly uncommon. 不幸的是,没有一种简单的方法可以在不复制大部分代码的情况下进行更改,因为更改Django模型的save()签名非常罕见。 You might be able to do something like this, although I'd recommend testing it carefully: 尽管我建议您仔细测试一下,但您也许可以执行以下操作:

from functools import partial

try:
    old_save = bundle.obj.save
    bundle.obj.save = partial(old_save, user=bundle.request.user)
    return super(FooResource, self).save(bundle)
finally:
    bundle.obj.save = old_save

References: 参考文献:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM