我的模型看起来像这样:
class Change(models.Model):
RFC = models.CharField(max_length=10)
Ticket_Number = models.CharField(max_length=10)
Plan_Owner = models.ForeignKey(User)
然后我通过以下方式在Django管理员中注册模型:
class ChangeAdmin(admin.ModelAdmin):
search_fields = ('RFC', 'Ticket_Number','Plan_Owner')
list_display = ('RFC', 'Ticket_Number','Plan_Owner')
fieldsets = [
('Ticket Details', {
'fields': ['RFC', 'Ticket_Number', 'Plan_Owner']}),
]
admin.site.register(Change, ChangeAdmin)
我想要实现的是确保特定更改的Plan_owner是唯一可以在超级用户之外编辑它的人。每个人都可以查看它,但计划所有者是唯一可以对其进行更改的人。另外通过编辑我的意思是,他可以做任何事情但删除一行。我已经看过Django监护人,它完全符合我的要求但是必须手动为每一行设置监护人的权限。我正在寻找一种解决方案,其中这些权限是根据我的要求自动设置的......
答案 0 :(得分:5)
我不会将对象级权限用于您的要求之类的简单内容。您只需要为您的模型提供owner
ForeignKey,并且只允许每个对象的所有者对其进行修改(您可以使用Plan_Owner
- 请将其更改为plan_owner
和Ticket_Number
到ticket_number
与pep 8和django style guide 兼容。
我写了一篇文章,描述了如何在django中执行此操作:
http://spapas.github.io/2013/11/05/django-authoritiy-data/
实际上我正在描述如何使用用户所属的权限,并且每个用户都可以编辑他的权限对象,但您的要求已被涵盖。
<强>更新强>
为了完整起见,我在这里添加了实现:
您的创建和更新基于类的视图必须将请求传递给您的表单,而您的详细信息和更新CBV应该只允许获取属于该用户的对象(假设您的模型名为UserData
:< / p>
class UserDataCreateView(CreateView):
model=models.UserData
def get_form_kwargs(self):
kwargs = super(UserDataCreateView, self).get_form_kwargs()
kwargs.update({'request': self.request})
return kwargs
class UserDataDetailView(DetailView):
def get_object(self, queryset=None):
obj = super(UserDataDetailView, self).get_object(queryset)
if not user_has_access(obj, self.request):
raise Http404(u"Access Denied")
return obj
class UserDataUpdateView(UpdateView):
model=models.AuthorityData
def get_form_kwargs(self):
kwargs = super(UserDataUpdateView, self).get_form_kwargs()
kwargs.update({'request': self.request})
return kwargs
def get_object(self, queryset=None):
obj = super(UserDataUpdateView, self).get_object(queryset)
if not user_has_access(obj, self.request):
raise Http404(u"Access Denied")
return obj
它检查request.user
是否具有权限(是对象的所有者),并将request
传递给ModelForm
。上面定义的has_access
函数只检查当前用户是否是对象的所有者:
def has_access(obj, req):
if req.user == obj.owner:
return True
return False
Yot ModelForm应该是这样的(创建/更新相同):
class UserDataModelForm(forms.ModelForm):
class Meta:
model = models.UserData
exclude = ('owner',)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(ActionModelForm, self).__init__(*args, **kwargs)
def save(self, force_insert=False, force_update=False, commit=True):
obj = super(UserDataModelForm, self).save(commit=False)
if obj:
obj.owner = self.request.user
obj.save()
return obj
它从request
中删除kwargs
并将其设置为属性,并在保存时将对象的所有者设置为reqest.user
。
答案 1 :(得分:0)
您可以通过覆盖get_queryset()类的ModelAdmin轻松地做到这一点。因此,get_queryset()是查询要在管理站点中显示的所有对象的地方。例如,如果您在get_queryset()中返回Change.objects.all()
,则将在管理站点中显示您Change
模型中的所有对象。如果您在get_queryset()中返回Change.objects.none()
,则不会在管理网站的Change
模型中显示任何值。
这是关于get_queryset()的文档。
返回查询集,该查询集将用于检索此视图将显示的对象。默认情况下,get_queryset()返回queryset属性的值(如果已设置),否则它通过调用QuerySet属性的默认管理器上的all()方法来构造model。 / p>
我只是在您的ChangeAdmin
类中覆盖get_queryset()。
class ChangeAdmin(admin.ModelAdmin):
model = Change
search_fields = ('RFC', 'Ticket_Number','Plan_Owner')
list_display = ('RFC', 'Ticket_Number','Plan_Owner')
fieldsets = [
(
'Ticket Details', {
'fields': ['RFC', 'Ticket_Number', 'Plan_Owner']
}
),
]
def get_queryset(self, request):
if request.user.is_superuser:
queryset = Change.objects.all()
else:
try:
queryset = Change.objects.filter(plan_owner_id=request.user.id)
except:
queryset = Change.objects.none()
return queryset
admin.site.register(Change, ChangeAdmin)
根据此示例,如果超级用户登录到管理站点,则他们将看到Change
模型中的所有对象。如果Change
表中的其他用户将显示他们自己的对象(因为在此示例中,它是根据Plan_Owner
模型的Change
进行过滤的),否则管理站点中将不显示任何内容