簡體   English   中英

Django:基於組的 model 的自定義權限

[英]Django: Custom permissions for group-based model

我是 Django 和 StackOverflow 的新手,所以請對我保持冷靜。 我將根據要求更新代碼和所有內容。

我目前正在開發一個系統,學生可以在該系統中加入名為 Societies 的組。 這些社團與用戶具有多對多字段關系。 我一直在想辦法建立一個系統,在每個社團內都有領導和一般成員。 領袖可以將會員提升為領袖,刪除社會中的帖子,甚至踢出社會成員。

我希望在正確的方向上獲得一些關於如何構建(或重新構建)我的代碼的指導,具體來說,我想知道如何將具有自定義權限的“領導者”用戶組合並為上述用戶。 然后我可以在我的模板中使用。 謝謝!

class Society(models.Model):
    name = models.CharField(max_length = 200)
    description = models.TextField()
    members = models.ManyToManyField(User, verbose_name=("Members"))

    def __str__(self):
        return f"{self.name}"

class SocPost(models.Model):
    title = models.CharField(max_length = 100)
    content = models.TextField()
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    society = models.ForeignKey(Society, on_delete=models.CASCADE, related_name="posts")

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('post-detail', kwargs={'society_id':self.society.id, 'pk':self.pk})

最簡單的解決方案是使用model


class SocietyMembership(models.Model)
    member = models.ForeignKey(User, related_name='society_membership')
    society = models.ForeignKey('Society')
    is_leader = models.BooleanField(default=False)

class Society(models.Model):
    name = models.CharField(max_length = 200)
    description = models.TextField()
    members = models.ManyToManyField(
        User,
        verbose_name=("Members"),
        related_name='societies',
        through=SocietyMembership
    )


    def __str__(self):
        return f"{self.name}"

這避免了由ContentTypes注入的額外查詢以及為每個社會創建一個領導組以將權限從一個組分離到下一個組的需要。


更新:

Model 更新:

class Society(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    members = models.ManyToManyField(
        User,
        verbose_name=_("Members"),
        related_name="societies",
        through=SocietyMembership,
    )

    @property
    def leaders(self):
        return self.memberships.filter(is_leader=True)

    def user_is_leader(self, user: User):
        return self.memberships.filter(is_leader=True, member=user).exists()

    def is_member(self, user: User):
        return self.members.filter(pk=user.id).exists()

    def __str__(self):
        return f"{self.name}"

    def enroll(self, user: User, as_leader: bool = False):
        # Django >= 2.2, which it should be in July 2020
        self.members.add(user, through_defaults={"is_leader": as_leader})

    def promote(self, user: User) -> bool:
        try:
            membership = self.memberships.get(member=user)
        except SocietyMembership.DoesNotExist:
            return False

        membership.is_leader = True
        membership.save()
        return True

    def kick(self, user: User):
        self.memberships.filter(member=user).delete()

具有權限檢查的視圖示例:

from django.views import generic
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
from . import models


class SocietyList(LoginRequiredMixin, generic.ListView):
    model = models.Society
    template_name = "main/society-list.html"
    context_object_name = "societies"


class SocietyDetail(UserPassesTestMixin, generic.DetailView):
    model = models.Society
    template_name = "main/society-detail.html"
    context_object_name = "society"

    def test_func(self):
        # self.object will be an instance of Society
        if not hasattr(self, "object"):
            setattr(self, "object", self.get_object())
        return self.object.is_member(self.request.user)

您似乎希望您的“領導者”成為管理員,由默認 django 用戶 model 中的“is_superuser”字段表示。 您所描述的是 Django 中的典型管理活動(並且可以在 django 管理面板中輕松完成)。 通過執行python manage.py createsuperuser創建這些超級用戶之一,然后您將可以訪問管理面板,您可以在其中自定義所需的一切,並將更多用戶提升到管理員級別。 如果您正在尋找基本用戶和管理員之間的某種程度的領導,您可以創建具有依賴於user_permissions字段的自定義權限的用戶,由您添加到 django 默認用戶 model 的某種變量表示,使用 1:1 關系。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM