一尘不染

Django-覆盖get_form以根据请求自定义管理表单

django

我尝试了各种方法来实现这一目标。

我决定不重写formfield_for_dbfield,因为它没有获得请求对象的副本,并且我希望避免对thread_locals的攻击。

我决定在ModelAdmin类中重写get_form并尝试以下操作:

class PageOptions(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        if request.user.is_superuser:
            self.fieldsets = ((None, {'fields': ('title','name',),}),)
        else:
            self.fieldsets = ((None, {'fields': ('title',),}),)
        return super(PageOptions,self).get_form(request, obj=None, **kwargs)

当我从get_form中打印字段集或声明的字段集时,我将获得None(或在PageOptions中设置为初始值的任何值)。

为什么这不起作用,还有更好的方法吗?


阅读 871

收藏
2020-04-02

共2个答案

一尘不染

我不知道为什么打印该属性不会给你想要分配的权限(我想可能完全取决于你打印的位置),但是尝试覆盖get_fieldsets。基本实现如下所示:

def get_fieldsets(self, request, obj=None):
    if self.declared_fieldsets:
        return self.declared_fieldsets
    form = self.get_formset(request).form
    return [(None, {'fields': form.base_fields.keys()})]

也就是说,你应该能够只返回你的元组。

由andybak编辑。4年后,当我尝试在另一个项目中做类似的事情时,我再次遇到了自己的问题。这次我采用了这种方法,尽管略作修改以避免重复字段集定义:

def get_fieldsets(self, request, obj=None):
    # Add 'item_type' on add forms and remove it on changeforms.
    fieldsets = super(ItemAdmin, self).get_fieldsets(request, obj)
    if not obj: # this is an add form
        if 'item_type' not in fieldsets[0][1]['fields']:
            fieldsets[0][1]['fields'] += ('item_type',)
    else: # this is a change form
        fieldsets[0][1]['fields'] = tuple(x for x in fieldsets[0][1]['fields'] if x!='item_type')
    return fieldsets
2020-04-02
一尘不染

我有一个我最近的项目中的示例代码,相信可以为你提供帮助。在此示例中,超级用户可以编辑每个字段,而其他所有人都将“ description”字段排除在外。

请注意,我认为应该Form从中返回一个类get_form,这可能就是为什么你的类不能正常工作的原因。

例子如下:

class EventForm(forms.ModelForm):
    class Meta:
        model = models.Event
        exclude = ['description',]

class EventAdminForm(forms.ModelForm):
    class Meta:
        model = models.Event

class EventAdmin(admin.ModelAdmin):

    def get_form(self, request, obj=None, **kwargs):
        if request.user.is_superuser:
            return EventAdminForm
        else:
            return EventForm 

admin.site.register(models.Event, EventAdmin)
2020-04-02