Django restframework权限

时间:2018-01-19 15:41:44

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

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

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

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

我是否需要创建自定义用户模型才能执行此操作?我该如何创建该模型,如何设置这些权限?

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

my 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')),
]

4 个答案:

答案 0 :(得分: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的用户角色,我将这些角色分配给不同的用户。

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

由于您希望将用户与公司相关联并对其应用权限逻辑,是的,可能使用自定义用户模型是最佳选择。您可以阅读有关如何执行此操作in the Django docs

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

答案 3 :(得分:0)

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

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)