假设我有:
models.py
class Books(models.Model):
owner = models.ForeignKey(User)
title = models.CharField(max_length = 100)
api.py
class UserResource(ModelResource):
#blhblahblah as usual
class BooksResource(ModelResource):
owner= fields.ToOneField(UserResource, 'owner')
class Meta:
queryset = Books.objects.all()
authorizarion = Authorization()
然后我发出:
curl --dump-header - -H "Content-Type: application/json" -X POST --data "{"owner" : "/api/v1/user/1/", "title" : "foo"}" http://localhost:8000/api/data/album/
它正在工作,我得到了我的新Books
然后我尝试通过将其添加到BooksResource
来摆脱"owner" : "/api/v1/user/1/"
def hydrate_owner(self, bundle):
bundle.obj.owner = User.objects.get(pk = bundle.request.user.id)
return bundle
当我在没有"owner" : "/api/v1/user/1/"
的情况下再次curl
时,响应是404 not found
然后我尝试不同的方法:
def obj_create(self, bundle, request = None, **kwargs):
return super(BooksResource, self).obj_create(bundle, request, owner = User.objects.get(pk = request.user.id))
或
def obj_create(self, bundle, request = None, **kwargs):
return super(BooksResource, self).obj_create(bundle, request, owner = User.objects.get(pk = bundle.request.user.id))
我仍然得到404 not found
伙计们能帮我吗?
Doh,显然这是我愚蠢的错误,
class BooksResource(ModelResource):
owner= fields.ToOneField(UserResource, 'owner')
class Meta:
queryset = Books.objects.all()
authorizarion = Authorization()
def hydrate_owner(self, bundle):
bundle.obj.owner = bundle.request.user.id
return bundle
错误是缩进! hydrate_owner
假设是BooksResource
方法,所以我稍微更改了代码,它可以工作:
class BooksResource(ModelResource):
owner= fields.ToOneField(UserResource, 'owner')
class Meta:
queryset = Books.objects.all()
authorizarion = Authorization()
def hydrate_owner(self, bundle):
bundle.data['owner'] = User.objects.get(pk = bundle.request.user.pk)
return bundle
我开始沿着这条路径为新对象设置所有者,但是在对更新请求进行授权检查时遇到了麻烦(进行单元测试!
设置:对象 A - 由用户 X 拥有更新来自用户 Y 的请求以修改对象 A(应失败)
对对象 A 的修改请求来自用户 Y 的 Tasty Pie,水合物覆盖将在对象 A 的工作副本中将所有者设置为 Y。
接下来,请求将发送到我的授权对象,以检查用户 Y 是否可以修改该对象。 我的授权代码在对象中查找,并看到对象的所有者字段为 Y,因此我们很好。 哎呀!安全漏洞!
我决定做的是覆盖资源模型中的obj_create()并在那里进行分配。 目前为止,一切都好!
例如
class SmApiNewsItem(ModelResource):
owner = fields.ForeignKey(SmApiUser, 'owner')
class Meta:
if SMARF_AUTH_ON:
authentication = ApiKeyAuthentication()
authorization = ScsGdnAuthVisibleToAllEditOnlyByOwner()
queryset = SmModelNewsItems.objects.all()
resource_name = 'news_item'
filtering = smMakeFilterAllFieldsFilter(SmModelNewsItems)
ordering = smMakeOrderingFieldList(SmModelNewsItems)
serializer = SmarfSerializer()
def obj_create(self, bundle, **kwargs):
bundle.data["owner"] = bundle.request.user
return super(SmApiNewsItem, self).obj_create(bundle, **kwargs)