Search code examples
pythondjangomodeladmin

Django admin add_view only renders up until change_view is displayed for first time


I'm experiencing a curious problem with Django's admin system and overriding the add_view and change_view methods to display different fields for adding and changing data. The add view works perfectly until the change view is displayed, then after that it will always display the change view instead of the add view when trying to add new data. I am using the latest release version of Django 1.9.4. My ModelAdmin class is quite simple:

@admin.register(Trigger)
class TriggerAdmin(admin.ModelAdmin):
    def add_view(self, request, **kwargs):
        self.fields = ('name', 'modules', 'trigger_event')
        self.filter_horizontal = ('modules',)
        return super(TriggerAdmin, self).add_view(request, **kwargs)

    def response_add(self, request, obj, **kwargs):
        return HttpResponseRedirect("../%s" % obj.id)

    def change_view(self, request, object_id, **kwargs):
        self.fieldsets = (
            (None, {'fields': ('name', 'modules')}),
            (_('Trigger'), {'fields': ('trigger_event', 'query', 'actions', 'is_active')})
        )
        self.readonly_fields = ('modules', 'trigger_event')
        return super(TriggerAdmin, self).change_view(request, object_id, **kwargs)

I have disabled all 3rd party apps and am only using the DummyCache. The only way to get the add view to show again after the change view has been displayed is to restart the site. I have checked that it is correctly calling the add_view method, its just going wrong at some point after that and showing the change_view instead.

I assume this is not a bug otherwise there would be others complaining about it, so I must be doing something wrong but I cannot see what it is.

Thanks,

Paul


Solution

  • It isn't safe to modify self.fields, self.fieldsets and self.readonly_fields like this. You are changing them for future requests as well as the current one.

    Instead of modifying these attributes in the add_view and change_view methods, you can override the get_fields, get_fieldsets, and get_readonly_fields instead. If the obj is None, then you are adding an object. For example:

    def get_fields(self, request, obj=None):
        if obj is None:
            return [<fields for add view>]
        else:
            return [<fields for change view>]