4

我试图限制组中的用户能够更改他们的组无权更改的字段。例如:

class StudentReferral(models.Model):
    teacher = models.CharField(max_length=50)
    referral_first_name = models.CharField(max_length=50)
    referral_last_name = models.CharField(max_length=50)
    accepted = models.BooleanField(blank=True)

现在教师都在一个用户组中,接受或拒绝推荐的人在另一个用户组中。教师用户组应该只能编辑以下字段teacherreferral_first_namereferral_last_name。其他用户组应该只能编辑接受的字段。两组都应该能够看到所有字段。

django 中是否有一些内置的东西可以使这成为可能,或者是一种自定义的方式来做到这一点?

4

1 回答 1

8

覆盖ModelAdmin.get_fieldsets,并执行以下操作:

class MyModelAdmin(admin.ModelAdmin):
    ...
    fieldsets = (
        ... # Standard/all fields
    )
    teacher_fieldsets = (
        ... # Only fields teachers can see
    )

    def get_fieldsets(self, request, obj=None):
        if request.user.groups.filter(name='Teachers').exists():
            return self.teacher_fieldsets
        else:
            return super(MyModelAdmin, self).get_fieldsets(request, obj=obj)

编辑

抱歉,我错过了关于他们仍然应该能够看到所有字段的信息,只是不能编辑它们。我已经完整地保留了原始答案,因为它可能仍然对您有用。但是,为此,您需要覆盖ModelAdmin.get_readonly_fields

class MyModelAdmin(admin.ModelAdmin):
    ...
    readonly_fields = ('teacher', 'referral_first_name', 'referral_last_name')
    teacher_readonly_fields = ('accepted',)

    def get_readonly_fields(self, request, obj=None):
        if request.user.groups.filter(name='Teachers').exists():
            return self.teacher_readonly_fields
        else:
            return super(MyModelAdmin, self).get_readonly_fields(request, obj=obj)

我在这里假设选择只有老师或“其他用户”。如果还有其他类型需要考虑,或者您不希望在一种情况下完全限制字段,您可能需要删除该readonly_fields属性并将其替换为类似的内容other_readonly_fields,并相应地分支(默认值readonly_fields仅是那些具有editable=False在模型上)。

另外,请注意,如果需要某个字段,您也不能将其设为只读。如果其中一些是必填字段,您还需要覆盖ModelForm.__init__,以使它们在只读的情况下不需要,这需要一些额外的hackery(ModelForm通常无权访问request):

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request')
        super(MyModelForm, self).__init__(*args, **kwargs)

        if self.request is not None:
            if self.request.user.groups.filter(name='Teachers').exists():
                self.fields['accepted'].required = False

class MyModelAdmin(admin.ModelAdmin):
    form = MyModelForm
    ...
    def get_form(self, request, obj=None, **kwargs):
        ModelForm = super(MyModelAdmin, self).get_form(request, obj=obj, **kwargs)
        class WrapperModelForm(ModelForm):
            def __new__(cls, *args, **kwargs):
                kwargs['request'] = request
                return ModelForm(*args, **kwargs)
        return WrapperModelForm
于 2012-07-19T20:51:18.687 回答