簡體   English   中英

如何實現Django多用戶類型,而一個用戶可以根據他/她所從事的項目具有不同的角色?

[英]How to implement Django multiple user types, while one user can have different role according to the project he/she is working on?

我找不到我的問題的解決方案,並希望對此發表評論/幫助。

我想在 Django 中開發一個多用戶類型模型,沿着作者使用 Django Proxy Models這個視頻的路線。

情況

我有一個 XX 項目列表( proj01proj02projXX ,...)。 所有這些項目都有其特定的頁面,可以通過特定的 url mysite/projXX/

我有多個用戶:Adam、Bob、Caroline、Dany、Ed、...

每個用戶可以根據他們所從事的項目擁有多個角色(例如經理、開發人員、紀錄片制作人、審閱者、編輯等)

用戶可以根據項目具有不同的角色。 例如,Adam 可以是 proj01 的審稿人,但可以是 proj02 的編輯,而 Bob 可以是 proj01 的編輯,但可以是 proj02 的審稿人,等等。

我開始在下面的models.py文件中定義多個用戶類型(只有審閱者和編輯者角色):

# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _


class User(AbstractUser):
    class Types(models.TextChoices):
        EDITOR= "EDITOR", "Editor"
        REVIEWER = "REVIEWER", "Reviewer"

    base_type = Types.EDITOR

    type = models.CharField(
        _("Type"), max_length=50, choices=Types.choices, default=base_type
    )

    name = models.CharField(_("Name of User"), blank=True, max_length=255)

    def get_absolute_url(self):
        return reverse("users:detail", kwargs={"username": self.username})

    def save(self, *args, **kwargs):
        if not self.id:
            self.type = self.base_type
        return super().save(*args, **kwargs)


class EditorManager(models.Manager):
    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(type=User.Types.EDITOR)


class ReviewerManager(models.Manager):
    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(type=User.Types.REVIEWER)


class EditorMore(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    gadgets = models.TextField()


class Editor(User):
    base_type = User.Types.EDITOR
    objects = EditorManager()

    class Meta:
        proxy = True

    def edit(self):
        return "Edition in progress"


class ReviewerMore(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    model = models.CharField(max_length=255)
    make = models.CharField(max_length=255)
    year = models.IntegerField()


class Reviewer(User):
    base_type = User.Types.REVIEWER
    objects = ReviewerManager()

    @property
    def more(self):
        return self.reviewermore

    class Meta:
        proxy = True

    def review(self):
        return "In Review" 

題:

處理用戶角色可以根據他/她正在訪問的項目頁面改變這一事實的最佳方法是什么?

示例:如果 Adam 登錄並訪問頁面mysite/proj01/我希望他只訪問評論者允許的內容,而如果 Adam 訪問mysite/proj02/ ,我希望用戶只看到允許的內容編輯。

理想情況下,我希望每個用戶在用戶數據庫中都有其唯一的條目。 我在想依賴於項目的角色級別可以存儲為字典嗎? 例如:

{'proj01':'reviewer', 'proj02':'editor', 'projxx': 'roleY', ... } 

如何將這個用戶模型和項目相關權限列表結合起來?

編輯 02/07/21

project應用程序、 models.pyviews.py添加示例文件:

# projects/models.py
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse


class Project(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(
        get_user_model(),
        on_delete=models.CASCADE,
    )

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("project_detail", args=[str(self.id)])

# projects/views.py
from django.contrib.auth.mixins import (
    LoginRequiredMixin,
    UserPassesTestMixin,
)
from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView, DeleteView, CreateView
from django.urls import reverse_lazy
from .models import Project


class ProjectListView(LoginRequiredMixin, ListView):
    model = Project
    template_name = "project_list.html"


class ProjectDetailView(LoginRequiredMixin, DetailView):
    model = Article
    template_name = "project_detail.html"


class ProjectUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = Project
    fields = (
        "title",
        "body",
    )
    template_name = "project_edit.html"

    def test_func(self):
        obj = self.get_object()
        return obj.author == self.request.user

如果您有項目作為模型。 您可以向模型添加自定義權限。 然后為每個項目適當地為您的用戶分配這些權限(實際上也很容易添加/刪除權限)。

然后在您的視圖/模板中使用 user_passes_test 或 permissions_required 來限制用戶可以查看/訪問/編輯的內容。

    class Project(models.Model):
       project_name = ...

    class RoleType(models.Model):
       role_name = models.CharField
       # Permission boolean flags
       can_edit = models.Boolean
       can_view = models.Boolean
       
    class ProjectRole(models.Model):
        project = models.ForeignKey('Project', ...)
        role = models.ForeignKey('RoleType', ...)
        user = models.ForeignKey('User', ...)

現在您可以根據項目或用戶反向查找

    # To show all assigned users and their roles for a project
    foo_project = Project.objects.get(project_name='foo')
    project_roles = ProjectRole.objects.filter(project=foo_project)

您還可以通過角色及其權限布爾標志來限制您的視圖和模板。

您可以將下面的示例作為參考。

楷模

class Project(models.Model):
    title = models.CharField(max_length=255)
 ......

class ProjectPermission(model.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='permissions')
    role = models.ForeignKey('Role', on_delete=models.CASCADE)
    can_add = models.BooleanField(default=False)
    can_review = models.BooleanField(default=False)
    .......

class Role(models.Model):
   name = models.CharField(max_length=50) # example Moderator etc.
   project_permissions = models.ManyToManyField(ProjectPermission)
   users = models.ManyToManyField(User)
   

觀看次數

#Let's create a Project instance
proj = Project.objects.create(title="Some Project")

#let's create role and assign users to role: 
role = Role.objects.create(name='Reviewer')
# assign users 
role.users.add(user1)

現在,例如,讓我們假設你要分配review權限最近創建的proj的內實例Reviewer角色:

# first create ProjectPermission 
perm = ProjectPermission.objects.create(project=proj, can_review=True, role=role)

# Now add this perm into the role:
role.project_permissions.add(perm)

現在終於可以查看用戶權限了。

 def review_project(request, project_id):
    project = Project.objects.get(id=project_id)
    if project.permissions.filter(can_review=True, role__users=request.user).exists():
       # your code
    else:
       raise PermissionDenied
  • 創建定義您的角色的組,例如:Group1: Editor、Group2:Manager 等
  • 將每個用戶分配到指定的組(您可以在 python manage.py shell 或管理面板中進行)
  • 對視圖添加限制,例如:/mysite/projx/ 視圖僅限於 groupA,您可以查看以下問題對您有幫助: https : //stackoverflow.com/a/4789038/13508969

例如: GroupA : GlobalEditor (Bob 可以在 projx 和 projy 中編輯,並且只能查看 projz )

GroupB:viewonly(Adam只能查看projs的內容)等等

暫無
暫無

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

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