【问题标题】:Tastypie - How to only authorize update a model through foreign keys?Tastypie - 如何仅授权通过外键更新模型?
【发布时间】:2017-11-27 13:15:54
【问题描述】:
A 有一个 Location 模型,它在许多模型中都是外键。不希望用户能够直接创建、编辑或删除位置(使用 /api/v1/location/ 端点),但我希望他们能够在创建一个将位置作为其外部对象的对象时钥匙。
例如:
/api/v1/event/
{
"name": "xxx",
"location": {
<new location>
}
}
有可能吗?
【问题讨论】:
标签:
python
django
api
tastypie
【解决方案1】:
我认为合理的解决方案是为同一模型设置 2 个单独的资源。一个用作独立资源,第二个用作事件内部的引用,两者都具有不同的授权规则。
class LocationLimitedResource(ModelResource):
# ...
class Meta:
serializer = Serializer(formats=['json'])
queryset = Location.objects.all()
resource_name = 'location_limited'
allowed_methods = ['get']
always_return_data = True
authentication = ApiKeyAuthentication()
authorization = LocationAuthorization()
# ...
class LocationResource(LocationLimitedResource):
class Meta(LocationLimitedResource.Meta):
allowed_methods = ['get', 'post', 'put', 'delete']
resource_name = 'location'
class EventResource(ModelResource):
location = fields.ForeignKey(LocationResource, 'location', full=True)
class Meta:
serializer = Serializer(formats=['json'])
queryset = Event.objects.all()
resource_name = 'event'
allowed_methods = ['get', 'post']
always_return_data = True
authentication = ApiKeyAuthentication()
authorization = EventAuthorization()
jobs_api = Api(api_name='v1')
jobs_api.register(LocationLimitedResource())
jobs_api.register(LocationResource())
jobs_api.register(EventResource())
我不太喜欢的另一种方式是:
class LocationAuthorization(Authorization):
# [...]
def create_detail(self, object_list, bundle):
return '/api/v1/event/' == bundle.request.path:
# [...]
class LocationResource():
# [...]
class Meta:
serializer = Serializer(formats=['json'])
queryset = Location.objects.all()
resource_name = 'location'
authorization = LocationAuthorization()
# [...]
这当然要求您硬编码您希望允许/禁止访问的资源的路径。一段时间后您可能会忘记该规则,这对于架构来说是不自然的。此外,API 的文档和自我发现也更加困难。