Luke
Luke

Reputation: 1834

django admin - overriding changelist_view for single entry models

I have a model for which i'll have one single instance, so i need to override the changelist_view to by-pass it (only if i have at least one record saved), and jump directly to change_view. i found snippet online and it works well for it, so i wrote my custom changelist_view:

def changelist_view(self, request, extra_context=None):
    queryset = self.model.objects.all()
    if queryset.count()>0:
        try:
            obj = queryset[0]
            return self.change_view(request, str(obj.id), extra_context)
        except IndexError:
            pass
    return super(MyModelAdmin, self).changelist_view(request, extra_context)

this works until I try to save. The difference from the normal change_view is in the url. the normal has the object id:

http://127.0.0.1:8000/admin/myapp/mymodel/2

instead with modified version i have:

http://127.0.0.1:8000/admin/myapp/mymodel/

if i try to save i got this error:

    You called this URL via POST, but the URL doesn't end 
    in a slash and you have APPEND_SLASH set. Django can't redirect to 
    the slash URL while maintaining POST data. Change your form to 
    point to 127.0.0.1:8000/admin/myapp1/mymodel/None/ (note 
    the trailing slash), or set APPEND_SLASH=False in your 
    Django settings.

At the moment the only trick that works for me is a HttpResponseRedirect(url), with as url the change_view url hardcoded with object id.

is there a more elegant way?

thanks Luke

Upvotes: 3

Views: 4867

Answers (2)

lacki
lacki

Reputation: 21

When using

def changelist_view(self, request, extra_context=None):

django will insert an action="None" in the Html output which causes the above mentioned error when submitting the post. Instead try

def changelist_view(self, request, extra_context=""):

Upvotes: 0

Peter DeGlopper
Peter DeGlopper

Reputation: 37319

You can change target URL the admin will redirect to after processing your edits by using the response_change method on your model admin. That receives the request and the changed object as parameters, and can return a redirect to a dynamically calculated URL.

def response_change(self, request, obj):
    # call the parent version to collect messages for the user
    original_response = super(MyModelAdmin, self).response_change(request, obj)
    if "_popup" in request.POST:
        return original_response
    return HttpResponseRedirect(reverse("admin:myapp_mymodel_change", args=[obj.id]))

There's also a response_add, but I doubt you'll need that if you're using a singleton model. Likewise, there are ways to test for whether the user selected "save and add another", "save and continue editing" or just "save" but you probably don't care about that distinction for a singleton.

Upvotes: 1

Related Questions