带参数的django UserPassesTestMixin

django UserPassesTestMixin with parameter

这是 user_passes_test 的工作版本。但我想用参数替换 position > 1 。我发现,可以使用 UserPassesTestMixin。但我不知道怎么办。有人可以帮忙吗?

models.py

class user_control(models.Model):
    user = models.ForeignKey(user, on_delete=CASCADE)    
    position = models.ForeignKey(position, on_delete=CASCADE)
    ...

views.py

def position_check(user):    
    position = 0 if user.is_anonymous else user_control.objects.values(
            'position__rank'
        ).get(
            user = user.id        
        )

    return True if position > 1 else False

@user_passes_test(position_check, login_url='loginPage')
def index(request):
   pass

@user_passes_test(position_check, login_url='loginPage')
def exportReview(request):
   pass

我试过:

class PositionCheckMixin(LoginRequiredMixin, UserPassesTestMixin):
    position_value = 2    

    def test_func(self):
        position = 0 if user.is_anonymous else user_control.objects.values(
                'position__rank'
            ).get(
                user = self.request.user.id        
            )
    
        return position > self.position_value

    def handle_no_permission(self):
        return redirect('loginPage')
    
class Review(PositionCheckMixin):
   position_value = 2

   def index(request):

您可以制作一个装饰器,例如采用可选参数:

def position_check(function=None, <strong>position_value</strong>=1, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
    def check(user):    
        position = 0 if user.is_anonymous else user_control.objects.values(
            'position__rank'
        ).get(
            user=user.id        
        )
        return position > <strong>position_value</strong>
    
    actual_decorator = user_passes_test(
        check,
        login_url=login_url,
        redirect_field_name=redirect_field_name,
    )
    if function:
        return actual_decorator(function)
    return actual_decorator

然后你可以使用装饰器:

@position_check(<strong>position_value=42</strong>, login_url='loginPage')
def index(request):
    # …
    pass

对于class-based视图,使用UserPassesTestMixin mixin [Django-doc]更方便:

class PositionCheckMixin(UserPassesTestMixin):
    <strong>position_value = 1</strong>
    
    def test_func(self):
        position = 0 if self.request.user.is_anonymous else user_control.objects.values(
            'position__rank'
        ).get(
            user=self.request.user.id
        )

        return position > <strong>self.position_value</strong>

然后您可以在 class-based 视图中将其与以下内容混合:

class MyView(<strong>PositionCheckMixin</strong>, View):
    <strong>position_value = 42</strong>
    
    # …