Django自定义装饰器user_passes_test()可以获取url参数吗?

时间:2016-09-11 22:55:26

标签: python django

Django user_passes_test()可以访问视图参数吗?

例如,我有一个视图,它接收id来检索特定记录:

def property(request, id):
    property = Property.objects.get(id=int(id))

该记录有一个名为user_id的字段,其中包含最初创建记录的用户的ID。我希望用户只能查看自己的记录,否则会被重定向。

我想使用看似简单干净的自定义装饰器。

对于自定义装饰器是否有一些类似的东西可以工作?

@user_passes_test(request.user.id = Property.objects.get(id=int(id)).id, login_url='/index/')
def property(request, id):
    property = Property.objects.get(id=int(id))

我尝试创建名为test_func的单独user_is_property_owner来包含将当前用户与属性记录user_id进行比较的逻辑

@user_passes_test(user_is_property_owner(id), login_url='/index/')
def property(request, id):
    property = Property.objects.get(id=int(id))


def user_is_property_owner(property_id):
    is_owner = False
    try:
        Property.objects.filter(id=property_id, user_id=user_id).exists()
        is_owner = True
    except Property.DoesNotExist:
        pass

但无法将当前用户ID和请求中的属性ID转换为user_is_property_owner装饰器功能。

编辑添加我正在使用的解决方案。我在每个视图测试中都进行了测试。很简单。我认为使用装饰器可能更漂亮,更简单。

def property(request, id):

    # get object 
    property = Property.objects.get(id=int(id))

    # test if request user is not user id on property record    
    if request.user.id != property.user_id:
        # user is not same as property user id so redirect to index
        return redirect('index')

    # rest of the code if request user is user_id on property record 
    # eg it is ok to let user into view 

1 个答案:

答案 0 :(得分:1)

通常,(使用基于类的视图),我将在get_queryset方法中处理此问题,因此它会像

一样
class PropertyDetail(DetailView):
    def get_queryset(self):
        return self.request.user.property_set.all()

如果属性不是当前用户,那将给出404。如果您最终获得的权限关系多于Property,则可能更喜欢使用django-guardian之类的项目。

如果您查看UserPassesTestMixin,则会在致电test_func之前看到它处理dispatch,因此如果您决定,您必须自己致电self.get_object(request)走那条路。