我正在尝试使用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
答案 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"权限,不再需要将其添加到模型中。