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