[Solved]-Adding link to django admin page


There are many ways to store the last visited non-admin url in request.session. For example, a middleware:

import re

class LastSiteUrl(object):
    def is_admin_url(self, url):
        return re.search('^(http:\/\/.*){0,1}\/admin\/', url) is not None

    def process_request(self, request):
        if self.is_admin_url(request.path) and \
            not self.is_admin_url(request.META.get('HTTP_REFERER','')):
            request.session['last_site_url'] = request.META.get('HTTP_REFERER','')

Then override the template:

  1. Store the last non admin url in request.session, e.g. put the above class in yourproject/middleware.py, add to settings.MIDDLEWARE_CLASSES: middleware.LastSiteUrl

  2. Prepare the admin base site template for overriding, copy django/contrib/admin/templates/admin/base_site.html to yourproject/templates/admin/base_site.html

  3. Link to request.session.last_site_url, e.g. in yourproject/templates/admin/base_site.html, find {% block branding %}, before the H1 tag of this block, add an HTML link to {{ request.session.last_site_url }}.

It should look like that:

{% block branding %}
    {% if request.session.last_site_url %}
        <a href="{{ request.session.last_site_url }}">back to site</a>
    {% endif %}
    <h1 id="site-name">{% trans 'Django administration' %}</h1>
{% endblock %}


The easy way:

If a model has a get_absolute_url function, the admin ‘change’ pages contain a ‘view on site’ button on the top right of the page. So make sure your Model contains get_absolute_url:

    def get_absolute_url(self):
        return '/myapp/%s' %self.slug #this should reflect your url-structure.

The ‘view on site’ button is not on the ‘add’ page because the object needs to be created before you can visit it. Tell your client when he/she is creating a new object to NOT hit ‘save’ but ‘save and continue editing’ and than click on ‘view on site’.

Now it’s also easy to jump to the website representation of the current model entry by overriding the base_site.html. Here we check if the current model contains absolute_url. If you are not on a change_page, there won’t be a absolute_url. In this case the link takes you to the homepage.


{% extends "admin/base.html" %}
{% load i18n %}

{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}

{% block branding %}
<h1 id="site-name">{% if has_absolute_url %}<a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% else %}<a href="http://{{ site.domain }}">{% endif %}{{ site.domain }}</a>    

 Sitebeheer{#{% trans 'Django administration' %}#}</h1>
{% endblock %}

{% block nav-global %}{% endblock %}


The following solution does also answer your question but in a different way. This will add a ‘save and view on site’ button next to ‘save and continue’ and ‘save’ buttons on the admin ‘add’ and ‘change’ pages:

  1. Make sure your model contains a get_absolute_url function.
  2. Override the admin response to redirect to this absolute_url.
  3. Override change_form.html to add a ‘save and view on site’ button.

Edit myproject/myapp/models.py

class MyModel(models.Model):
    title = models.CharField("titel", max_length=200)
    slug = models.SlugField(unique=True)

    def __unicode__(self):
        return self.title

    def get_absolute_url(self):
        return '/myapp/%s' %self.slug

Edit myproject/myapp/admin.py

from models import MyModel

class MyModelAdmin(admin.ModelAdmin):

    def response_change(self, request, obj):
        Determines the HttpResponse for the change_view stage.
        if request.POST.has_key("_viewsite"):
            msg = (_('The %(name)s "%(obj)s" was changed successfully.') %
                   {'name': force_unicode(obj._meta.verbose_name),
                    'obj': force_unicode(obj)})
            return HttpResponseRedirect(obj.get_absolute_url())
        return super(MyModel, self).response_change(request, obj)

admin.site.register(MyModel, MyModelAdmin)

Create a new file myproject/templates/admin/myapp/change_form.html:

{% extends "admin/change_form.html" %}
{% load i18n %}
{% block content %}
{{ block.super }}
<script type="text/javascript">//<![CDATA[
        $('<input type="submit" value="Save and view on site" name="_viewsite" />')
{% endblock %}

The template will override the change_form for each model in the myapp. This could be undesirable in your situation because not all models have a representation in the website (don’t have and don’t need get_absolute_url). I think you can also put the template at myproject/templates/admin/myapp/MyModel/change_form.html to only override the template for MyModel and leave other models in myapp with de default template. I never used a change_form template for a single model. Will you let me know if it worked?

A big thank you for: http://djangosnippets.org/snippets/2005/

Did this answer your question? I hope it helps.

Leave a comment