views:

1253

answers:

4

I've tried various methods to achieve this.

I decided against overriding formfield_for_dbfield as it's doesn't get a copy of the request object and I was hoping to avoid the thread_locals hack.

I settled on overriding get_form in my ModelAdmin class and tried the following:

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)

When I print fieldsets or declared_fieldsets from within get_form I get None (or whatever I set as an initial value in PageOptions).

Why doesn't this work and is there a better way to do this?

+4  A: 

I have some sample code from a recent project of mine that I believe may help you. In this example, super users can edit every field, while everyone else has the "description" field excluded.

Note that I think it's expected that you return a Form class from get_form, which could be why yours was not working quite right.

Here's the example:

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)
Ryan Duffield
That looks really helpful. I'm in the middle of a deadline right now but I'll try this out next week.PS Doesn't my super call result in a Form being returned? I'm just modifying the parameters and returning what get_form would have returned by itself.
andybak
A: 

I have no idea why printing the property doesn't give you want you just assigned (I guess may be that depends on where you print, exactly), but try overriding get_fieldsets instead. The base implementation looks like this:

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()})]

I.e. you should be able to just return your tuples.

miracle2k
+3  A: 

This is my solution:

class MyModelAdmin(admin.ModelAdmin):  

    def get_form(self, request, obj=None, **kwargs):
        if request.user.is_superuser:
            self.exclude = ()
        else:
            self.exclude = ('field_to_exclude',) 
        return super(MyModelAdmin, self).get_form(request, obj=None, **kwargs)

Hope can help

mdgart
Rather than removing the field, you may want to make it read-only (Django 1.2 and up) - just use self.readonly_fields instead of self.exclude.
jturnbull
A: 

Don't change the value of self attributes because it's not thread-safe. You need to use whatever hooks to override those values.

Ion Scerbatiuc