使用django-guardian进行djangorestframework的权限不起作用

时间:2019-02-03 14:30:22

标签: django django-rest-framework django-guardian

我正在尝试使用django-guardian向我的django REST项目添加对象级别权限,但是我得到了

http://127.0.0.1:8000/api/v1/tasks/

禁止使用HTTP 403 允许:GET,POST,HEAD,OPTIONS 内容类型:application / json 有所不同:接受

{     “ detail”:“您无权执行此操作。” }

用户joe已登录。

settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',

    'guardian',
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',

    'task.apps.TaskConfig',
]

models.py:

class Task(models.Model):
    summary = models.CharField(max_length=32)
    content = models.TextField()
    reported_by = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        permissions = (
            ('view_task', 'View task'),
        )

serializers.py:

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = '__all__'

permissions.py:

class CustomObjectPermissions(permissions.DjangoObjectPermissions):
    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
        'HEAD': ['%(app_label)s.view_%(model_name)s'],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

filters.py:

class DjangoObjectPermissionsFilter(BaseFilterBackend):
    perm_format = '%(app_label)s.view_%(model_name)s'
    shortcut_kwargs = {
        'accept_global_perms': False,
    }

    def __init__(self):
        assert 'guardian' in settings.INSTALLED_APPS, (
            'Using DjangoObjectPermissionsFilter, '
            'but django-guardian is not installed.')

    def filter_queryset(self, request, queryset, view):
        from guardian.shortcuts import get_objects_for_user

        user = request.user
        permission = self.perm_format % {
            'app_label': queryset.model._meta.app_label,
            'model_name': queryset.model._meta.model_name,
        }

        return get_objects_for_user(
            user, permission, queryset,
            **self.shortcut_kwargs)

views.py:

class TaskViewSet(viewsets.ModelViewSet):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
    permission_classes = (CustomObjectPermissions,)
    filter_backends = (DjangoObjectPermissionsFilter,)

urls.py:

router = DefaultRouter()

router.register('tasks', TaskViewSet, base_name='tasks')

urlpatterns = router.urls

但是它在shell中很好用

> python manage.py shell -i ipython
In [1]: from django.contrib.auth.models import User

In [2]: joe = User.objects.all().filter(username="joe")[0]

In [3]: import task.models as task_models

In [4]: task = task_models.Task.objects.all()[0]

In [5]: joe.has_perm('view_task', task)
Out[5]: True

1 个答案:

答案 0 :(得分:0)

API首先checks model-level permissions,然后是object-level permissions(如果适用)。由于自定义权限类要求用户具有读取权限,因此需要确保已为Joe分配了模型级别的读取访问权限。如果您勾选class App extends React.Component { componentDidMount() { this.props.getBackgroundImage(); } render() { return ( <div className="app"> {console.log(this.props.image)} (LINE 15) <Container photoProfile={this.props.photographerProfile} photoName={this.props.photographerName} /> </div> ); } } const mapStateToProps = state => { console.log(state); (LINE 26) console.log(state.image.urls); (LINE 27) return { image: state.image.urls // photographerProfile: state.image.user.links.html, // photographerName: state.image.user.name }; }; export default connect( mapStateToProps, { getBackgroundImage } )(App); ,我敢打赌它会返回joe.has_perm('tasks.view_task')。要解决此问题,您需要直接为其用户分配权限,或者将其添加到已分配适当权限的组中。

此外,请注意,Django 2.1最近添加了"view"权限,不再需要将其添加到模型中。