Django如何创建引用两个模型的验证混合?

问题描述

除了 User 类外,我还有两个 Organization 组织和 Staff 类。我想创建一个名为“ UserIsAdminMixin”的混入,以检查登录用户在特定组织中是否具有“管理员”角色。

类(简体)

class Organisation(models.Model):
    name = models.CharField(max_length=50)

class Staff(models.Model):
    class Role(models.TextChoices):
        ADMIN      = 'ADMIN',"Admin"
        STAFF      = 'STAFF',"Staff"

    user         = models.ForeignKey(settings.AUTH_USER_MODEL,null=True,blank=True,db_index=True,related_name="staff_profiles",on_delete=models.SET_NULL)
    organisation = models.ForeignKey('organisations.Organisation',related_name="staff",on_delete=models.CASCADE)
    role         = models.CharField(max_length=10,choices=Role.choices,default=Role.STAFF)

然后,我现在将其用于UserIsAdmin mixin:

class UserIsAdminMixin:

    def dispatch(self,request,*args,**kwargs):
        if self.request.user.staff_profiles.filter(organisation=self.get_object(),role=Staff.Role.ADMIN):
            return super().dispatch(request,**kwargs)
        else:
            raise PermissionDenied

这对于此视图非常有用:

organisations.views.py(URL:Organisation /

class OrganisationDetail(LoginrequiredMixin,UserIsAdminMixin,generic.DetailView):
    model = Organisation
    template_name= "organisations/detail.html"
    login_url = "login"

但是我也希望它也适用于此视图,它显然不适合self.get_object()在这种情况下,当它期望一个Organization对象时会返回一个Staff对象:

staff.views.py(URL:Organisation / / staff /

class StaffDetail(LoginrequiredMixin,generic.DetailView):
    model = Staff
    template_name="staff/detail.html"
    login_url = "login"

我能够对mixin进行更改,以使其能够在第二种情况下工作,而在第一种情况下无法工作:

class UserIsAdminMixin:

    def dispatch(self,**kwargs):
        if self.request.user.staff_profiles.filter(organisation__pk=self.kwargs['pk_alt']),**kwargs)
        else:
            raise PermissionDenied

所以我有什么办法可以更改混合,以便它对两者 组织 Staff 模型都适用,以检查用户是否是负责给定组织的工作人员?

任何帮助将不胜感激!

非常感谢,

GoingRoundInCircles

解决方法

嗯,可能的解决方案是在两个视图中都使用get_organisation_id()方法。

您的混音:

class UserIsAdminMixin:

    def dispatch(self,request,*args,**kwargs):
        organisation_id = self.get_organisation_id()
        if self.request.user.staff_profiles.filter(organisation_pk=organisation_id,role=Staff.Role.ADMIN):
            return super().dispatch(request,**kwargs)
        else:
            raise PermissionDenied

StaffDetail

class StaffDetail(LoginRequiredMixin,UserIsAdminMixin,generic.DetailView):
    model = Staff
    template_name="staff/detail.html"
    login_url = "login"

    def get_organisation_id(self):
        return self.kwargs.get('pk_alt')

组织详细信息:

class OrganisationDetail(LoginRequiredMixin,generic.DetailView):
    model = Organisation
    template_name= "organisations/detail.html"
    login_url = "login"

    def get_organisation_id(self):
        return self.get_object().id