【问题标题】:Django restframework permissionsDjango 休息框架权限
【发布时间】:2018-01-23 18:33:38
【问题描述】:

这是一个基本的api,我有3种用户->管理员、公司、员工。

管理员可以查看、编辑和删除所有视频,公司可以查看和删除其员工,员工只能看到其公司更新的视频。

所以每个公司都会有一个管理面板,他们可以上传培训视频和注册员工,所以每个公司都有自己的面板,他们看不到其他公司。

我是否需要创建自定义用户模型才能做到这一点?我将如何创建该模型,如何设置这些权限?

如何管理公司和员工可以访问或不能访问的注册表单、登录名、网址

我的models.py:

from django.db import models
from django.utils import timezone

# Create your models here.
class Company(models.Model):
    user = models.ForeignKey('auth.User', on_delete=models.DO_NOTHING)
    empresa_nome = models.CharField(max_length=100, default='')
    razao_social = models.CharField(max_length=100, default='')
    cnpj = models.CharField(max_length=18, default='')

    def __str__(self):
        return self.empresa_nome


class Employee(models.Model):
    empresa = models.ForeignKey(Company, on_delete=models.DO_NOTHING, related_name='employees')
    user = models.ForeignKey('auth.User', on_delete=models.DO_NOTHING)
    phone = models.CharField(max_length=20)

    def __str__(self):
        return self.phone


class Test(models.Model):
    company = models.ForeignKey(Company, on_delete=models.DO_NOTHING, related_name='treinamentos')
    user = models.ForeignKey('auth.User', on_delete=models.DO_NOTHING)
    categoria = models.CharField(max_length=100)
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(auto_now_add=True)


    def __str__(self):
        return self.categoria


class Video(models.Model):
    video = models.ForeignKey(Test, on_delete=models.DO_NOTHING, related_name='video')
    user = models.ForeignKey('auth.User', on_delete=models.DO_NOTHING)
    url = models.CharField(max_length=150)
    ordem = models.IntegerField(null=False)
    pergunta = models.CharField(max_length=250)
    certo = models.CharField(max_length=250)
    errado = models.CharField(max_length=250)
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(auto_now_add=True)


    def __str__(self):
        return self.categoria

serializers.py:

from django.contrib.auth.models import User
from rest_framework import serializers

from .models import Company, Employee, Test, Video

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('url', 'username', 'email', 'is_staff')


class EmployeeSerializer(serializers.ModelSerializer):

    class Meta:
        model = Employee
        exclude = []


class VideoSerializer(serializers.ModelSerializer):

    class Meta:
        model = Video
        exclude = []


class TestSerializer(serializers.ModelSerializer):
    video = VideoSerializer(read_only=True, many=True)
    class Meta:
        model = Test
        fields = ('id', 'categoria', 'video', 'created_at', 'updated_at')
        exclude = []


class CompanySerializer(serializers.ModelSerializer):
    employees = EmployeeSerializer(read_only=True, many=True)
    treinamentos = TestSerializer(read_only=True, many=True)
    #user_obj = UserSerializer(read_only=True)
    class Meta:
        model = Company
        fields = ('id', 'empresa_nome', 'razao_social', 'cnpj', 'employees', 'treinamentos')
        exclude = []

urls.py

from django.conf.urls import url, include
from django.contrib import admin
from rest_framework import routers, viewsets
from restcompanies.views import UserViewSet, CompanyViewSet, EmployeeViewSet, TestViewSet, VideoViewSet

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'companies', CompanyViewSet)
router.register(r'employees', EmployeeViewSet)
router.register(r'tests', TestViewSet)
router.register(r'videos', VideoViewSet)

app_name = 'restcompanies'

urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^admin/', admin.site.urls),
    url(r'^api-auth/', include('rest_framework.urls', namespace='restcompanies')),
]

【问题讨论】:

  • 你能分享一下你到目前为止的尝试吗?
  • @arjun27 我已经用一些代码更新了问题

标签: django python-3.x rest permissions django-rest-framework


【解决方案1】:

您可以通过检查模板中的权限并根据权限分支渲染来修改视图。例如,您可以设置一个“can_edit”标志并将其传递回上下文中。然后在你的模板中做:

{% if can_edit %}
*edit only code goes here
{% endif %}

或者,您可以根据角色和公司为同一视图提供不同的模板。这可以通过使用 TemplateView 并覆盖 get_template_names 来完成,例如

class AdminView(TemplateView):


def get_template_names(self):
    if empresa_nome == 'company1':
        return 'company1template.html'

但在我看来,后一种解决方案只有在模板完全不同的情况下才是好的,而如果它只是在类似模板中启用/禁用选项,那么第一种解决方案会更好。

您不一定需要自定义用户模型,因为默认情况下您可以在 django 中创建许多不同的角色并将这些角色分配给用户。例如,在一个项目中,我使用用户角色检查权限:

def checkPermissions(request):
    if not request.user.is_authenticated():
        return None
    if request.user.groups.filter(name='MerchantSuperAdmin').exists() or request.user.is_superuser:
        return 'SU' #can access whatever
    if request.user.groups.count() == 1 and request.user.groups.filter(name='employee').exists():
        return 'readonly'

在这种情况下,我有一个名为 MerchantSuperAdmin 的自定义用户角色和另一个名为 Employee 的自定义用户角色,我将它们分配给不同的用户。

... 等等。然后在模板中,您可以根据 context['permission'] 或类似内容选择 javascript 的 html。

【讨论】:

    【解决方案2】:

    在 django 中,权限是基于模型/类的,而不是基于实例/对象的。如果您希望它们基于对象,则必须编写自己的权限模型或(我建议这样做)使用执行此操作的现有软件包之一。我喜欢的一个包是 django-guardian (https://django-guardian.readthedocs.io/en/stable/),它有很好的文档并且很容易使用。此外,由于您使用的是 django rest 框架,因此很有可能已经安装了它,因为 django rest 在其安装说明中将其列为可选包之一。

    【讨论】:

      【解决方案3】:

      由于您希望将用户与公司相关联并对其应用权限逻辑,是的,可能使用自定义用户模型是最佳选择。你可以阅读如何做到这一点in the Django docs

      Django Rest Framework 允许您根据任意条件(包括所请求的资源)允许/禁止访问视图。请参阅documentation section about custom permissions

      【讨论】:

        【解决方案4】:

        我会使用继承的自定义权限。

        http://www.django-rest-framework.org/api-guide/permissions/#custom-permissions

        class IsAdmin(permissions.BasePermission):
            def has_permission(self, request, view):
                return do_some_custom_checking(...)
        
        class IsCompany(IsAdmin):
            def has_permission(self, request, view):
                return do_some_custom_checking(...) or super(IsCompany, self).has_permission(request, view)
        
        class IsEmployee(IsCompany):
            def has_permission(self, request view):
                return do_some_custom_checking(....) or super(IsEmployee, self).has_permission(request, view)
        

        【讨论】:

          猜你喜欢
          • 2023-03-18
          • 2013-04-08
          • 2021-05-23
          • 2021-11-26
          • 1970-01-01
          • 1970-01-01
          • 2015-02-25
          相关资源
          最近更新 更多