如何从 BasePermission 中访问 URL 参数?
How can I access URL parameters from within a BasePermission?
我正在尝试编写自定义 rest_framework 权限以防止用户查询与他们不属于同一公司的信息。不幸的是,我似乎无法从 has_permission()
或 has_object_permissions()
.
中访问任何 URL 的参数
这是我的路由器的开头:
# Create a basic router
router = routers.SimpleRouter()
# Establish some variables to assist with nested routes
root_elem = 'companies'
root_elem_id = '/(?P<company_id>[0-9]+)'
loca_elem = '/locations'
loca_elem_id = '/(?P<location_id>[0-9]+)'
# Companies will be the root from which all other relations branch
router.register(r'' + root_elem, views.CompanyViewSet)
router.register(r'' + root_elem + root_elem_id + loca_elem,
views.LocationViewSet)
这是我的自定义权限:
# Only permit actions originating from location managers or company admins
class IsLocationManagerOrHigher(BasePermission):
# Checked when displaying lists of records
def has_permission(self, request, *args, **kwargs):
is_correct_level = False
# Admins can see every location if their location_id
# matches a location that's a child of the company
# specified in the URL
if request.employee.is_admin:
is_correct_level = True
return request.user and is_correct_level
# Checked when viewing specific records
def has_object_permission(self, request, view, obj):
is_correct_level = False
# Admins can see location details if their location's company_id
# matches a Location's company_id
if request.employee.is_admin:
is_correct_level = True
# Managers can see location details if it's their location
elif obj.id == request.employee.location_id and request.employee.is_manager:
is_correct_level = True
return request.user and is_correct_level
现在检查 request.employee.is_admin
只是我需要的一半 - 我还需要从 URL 访问 company_id
并确保它与管理员的位置匹配 company_id
:
# Pseudocode
try:
user_location = Location.objects.get(id=request.employee.location_id)
return user_location.company_id == kwargs['company_id']
except ObjectDoesNotExist:
pass
我还没有弄清楚如何将这些参数传递给 Permission,以便它可以执行这个额外的步骤。或者也许有更好的方法来完成我想做的事情?
如果您不能直接传递它们(这会更好),它们在请求对象上可用:
company_id = request.resolver_match.kwargs.get('company_id')
request.resolver_match.args
和 request.resolver_match.kwargs
包含在您的 url 中捕获的 positional/keyword 参数。
作为 knbk 发布的正确响应的替代方法,您还可以使用传递给 has_permission 方法的视图对象获取 URL 参数。像这样:
company_id = view.kwargs.get('company_id')
我正在尝试编写自定义 rest_framework 权限以防止用户查询与他们不属于同一公司的信息。不幸的是,我似乎无法从 has_permission()
或 has_object_permissions()
.
这是我的路由器的开头:
# Create a basic router
router = routers.SimpleRouter()
# Establish some variables to assist with nested routes
root_elem = 'companies'
root_elem_id = '/(?P<company_id>[0-9]+)'
loca_elem = '/locations'
loca_elem_id = '/(?P<location_id>[0-9]+)'
# Companies will be the root from which all other relations branch
router.register(r'' + root_elem, views.CompanyViewSet)
router.register(r'' + root_elem + root_elem_id + loca_elem,
views.LocationViewSet)
这是我的自定义权限:
# Only permit actions originating from location managers or company admins
class IsLocationManagerOrHigher(BasePermission):
# Checked when displaying lists of records
def has_permission(self, request, *args, **kwargs):
is_correct_level = False
# Admins can see every location if their location_id
# matches a location that's a child of the company
# specified in the URL
if request.employee.is_admin:
is_correct_level = True
return request.user and is_correct_level
# Checked when viewing specific records
def has_object_permission(self, request, view, obj):
is_correct_level = False
# Admins can see location details if their location's company_id
# matches a Location's company_id
if request.employee.is_admin:
is_correct_level = True
# Managers can see location details if it's their location
elif obj.id == request.employee.location_id and request.employee.is_manager:
is_correct_level = True
return request.user and is_correct_level
现在检查 request.employee.is_admin
只是我需要的一半 - 我还需要从 URL 访问 company_id
并确保它与管理员的位置匹配 company_id
:
# Pseudocode
try:
user_location = Location.objects.get(id=request.employee.location_id)
return user_location.company_id == kwargs['company_id']
except ObjectDoesNotExist:
pass
我还没有弄清楚如何将这些参数传递给 Permission,以便它可以执行这个额外的步骤。或者也许有更好的方法来完成我想做的事情?
如果您不能直接传递它们(这会更好),它们在请求对象上可用:
company_id = request.resolver_match.kwargs.get('company_id')
request.resolver_match.args
和 request.resolver_match.kwargs
包含在您的 url 中捕获的 positional/keyword 参数。
作为 knbk 发布的正确响应的替代方法,您还可以使用传递给 has_permission 方法的视图对象获取 URL 参数。像这样:
company_id = view.kwargs.get('company_id')