django - 如何使用装饰器检查用户是否有权访问 Django 中的某些对象

标签 django backend decorator

我正在开发一个项目,其结构如下。我试图检查用户是否是所请求团队的成员并允许查看其详细信息。所以我试图通过装饰器来实现这一点,但我仍然收到 http 500 错误。

我不确定这是否是正确的解决方案和糟糕的实现,或者最好以不同的方式实现。

我将非常感谢您的帮助。

团队/模型.py

roles = (('admin', 'admin'), ('member', 'member'), ('guest', 'guest'))

class Team(models.Model):
    name = models.CharField(max_length=150)
    description = models.TextField(blank=True)
    members = models.ManyToManyField(User, through='Membership')
    cppTables = models.JSONField(default=list, blank=True)
    
    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return f'teams/{self.pk}/'

    def has_user(self, user_id):
        return self.members.get(pk=user_id).exists()

class Membership(models.Model):
    member = models.ForeignKey(User, on_delete=models.CASCADE)
    team = models.ForeignKey(Team, on_delete=models.CASCADE)
    role = models.CharField(max_length=15, choices=roles, default='member')

    def __str__(self):
        return str(self.member)

    class Meta:
        unique_together = [['member', 'team']]

Team/Decorators.py

def required_membership(view_func):
    def wrapper(request, *args, **kwargs):
        team_id = kwargs['team_id']
        team = Team.objects.get(pk=team_id)
        if team.has_user(request.user.id):
            return view_func(request, *args, **kwargs)
        else:
            raise HttpResponseForbidden
    return wrapper

团队/Views.py

@method_decorator(required_membership, name="dispatch")
class TeamDetail(APIView):
    def get_object(self, pk):
        try:
            return Team.objects.get(pk=int(pk))
        except Team.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        team = self.get_object(pk)
        serializer = TeamSerializer(team, many=False)
        return Response(serializer.data)

最佳答案

在装饰器中将包装器放入内部函数中。您的代码将如下所示,并且无需将其放入方法装饰器中,只需像这样 @required_membership()

from django.core.exceptions import PermissionDenied
def required_membership():
    def inner(view_func):
        def wrapper(request, *args, **kwargs):
            team_id = kwargs['team_id']
            team = Team.objects.get(pk=team_id)
            if team.has_user(request.user.id):
                return view_func(request, *args, **kwargs)
            else:
                raise PermissionDenied
        return wrapper


    return inner

更新

将装饰器放在 get 或 post 方法而不是类之上

关于django - 如何使用装饰器检查用户是否有权访问 Django 中的某些对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70529674/

相关文章:

sql - 在 django ORM 中使用 postgresql 窗口函数的干净方法?

用不同语言编写的API框架的性能基准

java - 如何从后端运行 Google 应用引擎端点方法

python - 为什么 Python 的 @staticmethods 与装饰类的交互如此糟糕?

javascript - TypeScript 装饰器中的异步调用

python - Django 管理模型字段设置为当前用户

django.db.utils.IntegrityError : UNIQUE constraint failed: rango_category__new. slug

angularjs - 使用 Ionic 作为前端、Django 作为后端开发移动应用程序

wordpress - 我应该使用 WordPress 作为移动应用程序的后端吗

python,混淆装饰和关闭