您如何确保用户只能编辑他们创建的对象?设置它的最佳方法是什么?
我正在使用django-rest-framework,并想知道是否有办法限制用户查看/编辑他们不"拥有"的对象.
class Video(models.Model):
owner = models.ForeignKey(User)
...
Run Code Online (Sandbox Code Playgroud)
因此,用户'x'应该只能在其owner_set中编辑视频.
我在我的Django应用程序中定义了一个模型foo,如下所示:
class Bar(models.Model):
class Meta:
permissions = (
("view_bar", "Can view bars"),
)
Run Code Online (Sandbox Code Playgroud)
我已经跑manage.py syncdb了这个,果然,它出现在auth_permissions表格中:
id|name|content_type_id|codename
41|Can view bars|12|view_bar
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试将该权限添加到视图中的用户对象时,如下所示:
request.user.user_permissions.add('foo.view_bar')
Run Code Online (Sandbox Code Playgroud)
代码爆炸,出现以下异常:
invalid literal for int() with base 10: 'foo.view_bar'
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?
我正在启动一个具有复杂权限结构的应用程序,该结构将不可避免地由用户自己管理。我在模型中具有以下权限:
class Meta:
permissions = (
('can_view', 'View project'),
('manage_view', 'Can assign View project'),
('can_edit', 'Edit project'),
('manage_edit', 'Can assign Edit project'),
('can_delete', 'Delete project'),
('manage_delete', 'Can assign Delete project'),
('creator', 'Full access to model features.'),
)
Run Code Online (Sandbox Code Playgroud)
这些将在Django-guardian的对象级别进行管理,而我正在使用自定义mixins处理所有各种组合和功能。
“创建者”权限分配给对象的初始创建者,他们可以通过基于电子邮件的邀请系统将其他权限分配给用户。
我的问题围绕着选项,这些选项用于分配创建者对对象的创建权限。
到目前为止,我想到的一些方法是:
保存后在视图中分配
newObject.save()
assign('creator', User, newObject)
Run Code Online (Sandbox Code Playgroud)
通常,我更喜欢从我的观点中排除此类事件。
覆盖save()
这种方法的问题是我必须授予对User对象的保存访问权限,这意味着也要覆盖init以设置self.request = request。
后保存信号
我知道我可以利用此信号,但是与前两个信号相比,我还没有尝试实现此信号。
希望这可以对我所处的事物提供足够的洞见。
我很想知道这些方法中最好的是什么,或者如果它们都是坏主意,那么可以选择什么替代实现。
谢谢,
京东
最终,我的目标是扩展 Django 的 ModelAdmin 以提供字段级权限——也就是说,给定请求对象的属性和正在编辑的对象字段的值,我想控制字段/内联是否可见给用户。我最终通过向can_view_field()ModelAdmin添加一个方法并修改内置get_form()和get_fieldset()方法来删除/排除用户没有权限(由 确定can_view_field())查看的字段+内联来完成此操作。如果你想看代码,我把它放在了一个 pastebin 中,因为它很长而且只是有点相关。
它工作得很好......几乎。我似乎遇到了某种线程安全或缓存问题,其中 ModelAdmin 对象的状态以可重现的方式从一个请求泄漏到另一个请求。
我会用一个简单的例子来说明这个问题。假设我有一个模型,我使用字段级权限代码对其 ModelAdmin 进行了扩展。该模型有两个字段: - public_field,任何工作人员都可以看到/编辑 - secret_field,只有超级用户才能看到/编辑
在这种情况下,该can_view_field()方法将如下所示:
def can_view_field(self, request, obj, field_name):
"""
Returns boolean indicating whether the user has necessary permissions to
view the passed field.
"""
if obj is None:
return request.user.has_perm('%s.%s_%s' % (
self.opts.app_label,
action,
obj.__class__.__name__.lower()
))
else:
if field_name == "public_field":
return True
if field_name == "secret_field" and request.is_superuser:
return …Run Code Online (Sandbox Code Playgroud) 我需要为管理员进行"所有者"登录.假设我们有这个模型结构:
class Product(models.Model):
owner = models.ManyToManyField(User)
name = models.CharField(max_length=255)
description = models.CharField(max_length=255)
photos = models.ManyToManyField(Photo, through='ProductPhoto')
class Photo(models.Model):
order = models.IntegerField()
image = models.ImageField(upload_to='photos')
alt = models.CharField(max_length=255)
class ProductPhoto(models.Model):
photo = models.ForeignKey(Photo)
product = models.ForeignKey(Product)
Run Code Online (Sandbox Code Playgroud)
我们有一个组称为Owners某些用户是其中的一部分.这ProductPhoto是管理页面TabularInline上的一个Product.
现在,所有者需要编辑权限
(主要目标) 只有产品在哪里product__in=user.products(所以基本上只有他们拥有的产品).
(次要目标) 只是在描述和照片的产品
如何使用Django的管理/权限系统执行此操作?
Django和编程新手在这里。我已经制作了一个要部署的应用程序,但是我需要弄清楚如何将对UpdateView的访问限制为该对象的创建者,这让我很沮丧。
当前,用户可以使用CreateView ... / universities / create /创建大学对象,但是任何用户都可以使用... / universities / update /编辑该对象。我要配置它,以便只有作为该大学的创建者的用户(任何具有ManytoMany属性“ administrator”的用户)才可以访问其大学对象的UpdateView。
任何意见,将不胜感激。我已经花了几天的时间,但是我并没有做太多的事情……感谢您的阅读。
models.py
class University(models.Model):
name = models.CharField(max_length=100)
about = models.TextField()
administrators = models.ManyToManyField(User)
profile_picture = models.FileField(upload_to=get_upload_file_name, blank=True)
def __unicode__(self):
return unicode(self.name)
def get_absolute_url(self):
return reverse('university_detail', kwargs={'pk': str(self.id)})
Run Code Online (Sandbox Code Playgroud)
views.py
class UniversityCreateView(CreateView):
model = University
form_class = UniversityForm
template_name = 'university_create.html'
def form_valid(self, form):
f = form.save(commit=False)
f.save()
return super(UniversityCreateView, self).form_valid(form)
class UniversityUpdateView(UpdateView):
model = University
form_class = UniversityForm
template_name='university_form.html'
Run Code Online (Sandbox Code Playgroud) 我的用户类别是:
class UserProfile(User):
sex = models.SmallIntegerField(verbose_name=_(u'sex'), choices=SEX_TYPES, default=1)
.
.
Run Code Online (Sandbox Code Playgroud)
UserProfileSerializer:
class ProfileSerializer(serializers.ModelSerializer):
groups = GroupSerializer()
class Meta:
model = UserProfile
fields = ('id', 'first_name', 'last_name', 'username','email','groups')
Run Code Online (Sandbox Code Playgroud)
允许用户注册的api视图是:
@api_view(['POST'])
def create_user(request):
serialized = ProfileSerializer(data=request.DATA)
if serialized.is_valid():
created_user = UserProfile.objects.create_user(
serialized.init_data['email'],
serialized.init_data['username'],
serialized.init_data['password'],
)
# here I want assign a group for user or anything else
created_user.groups = "users"
created_user.save()
return Response(serialized.data, status=status.HTTP_201_CREATED)
else:
return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)
通过此测试:
curl -X POST -H "Content-Type: application/json" -d '
{
"username": "aaa",
"email": "aa@aaa.com" …Run Code Online (Sandbox Code Playgroud) 我想在我的 Django 应用程序中拥有层次级别权限。
例如:- 考虑有 4 个级别 -
Admin
Sub-admin(CountryLevel(CL) Admin)
sub-sub-admin(StateLevel(SL) Admin)
And then normal Users(U).
Run Code Online (Sandbox Code Playgroud)
管理员将创建 CL,作为回报,CL 将创建 SL,而 SL 最终将吸引用户。最终目标是吸引用户。
管理员有权对任何用户应用 CRUD 操作。CL 应该有权访问由 CL 创建的 SL 加入(创建)的用户(对象)。作为回报,SL 应该只能访问由他加入(创建)的那些用户(对象)。此外,用户可以直接注册,无需任何管理员参与。在这种情况下,用户应有权访问他自己的应用程序。
我怎样才能获得像树级别的权限?
我能想到的解决方案是(但不确定):-
我已经更新了auth_group表格并添加parent_id到其中。以下是架构。
id, group_name, parent_id
Run Code Online (Sandbox Code Playgroud)
的意义parent_id在于创建一个树状的组结构。创建的组数等于树的高度。例如,考虑以下结构:-
id, group_name, parent_id
1 , admin, 0
2, CL, 1
3, SL, 2
Run Code Online (Sandbox Code Playgroud)
现在,当创建任何用户(加入)时,我将分配一个SL group_id,它将添加到auth_user_groups表中。
现在,我想问以下问题
1)如何管理组的层次权限,即SL应该只能访问他所加入的用户,CL应该能够访问他创建的SL所加入的所有用户等等。
2)(不确定我的想法是否正确)现在,由于我已将组 SL 分配给 SL 加入的所有用户,作为同一组的一部分,用户是否能够访问彼此的信息?
3) 对于直接加入的用户(即不通过任何 SL),我不会将他们映射到任何组。正确的?
我有一个基本的视图集:
class UsersViewSet(viewsets.ModelViewSet):
permission_classes = (OnlyStaff,)
queryset = User.objects.all()
serializer_class = UserSerializer
Run Code Online (Sandbox Code Playgroud)
它绑定到/api/users/端点。我想创建一个用户个人资料页面,所以我只需要一个特定的用户,所以我可以从中检索它/api/users/<id>/,但问题是我想/api/users/<id>/被允许给任何人,但/api/users/要保留其权限OnlyStaff,所以没有人可以访问完整的用户列表。
注意:也许这不是一个很好的实现,因为任何人都可以蛮力增加 的数据id,但我愿意将其从 更改<id>为<slug>。
如何从详细路线中删除权限?
提前致谢。
我偶然发现了一个奇怪的行为:我向用户对象添加了权限,但权限检查失败。
permission = Permission.objects.get_by_natural_key(app_label='myapp', codename='my_codename', model='mymodel')
user.user_permissions.add(permission)
user.has_permission('myapp.my_codename') # this is False!
Run Code Online (Sandbox Code Playgroud)
我在这里和这里找到了一些关于用户权限缓存的帖子,解决方案似乎是从数据库完全重新加载对象。
# Request new instance of User
user = get_object_or_404(pk=user_id)
# Now note how the permissions have been updated
user.has_perms('myapp.my_codename') # now it's True
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎太过分了,而且非常不像 django。是否真的没有办法清除权限缓存或重新加载外键,就像您可以对对象执行的那样refresh_from_db()?
提前致谢!
罗尼