Stupid-Simple Django Admin Previews

Incase you didn’t know, I love Django.

I love how Django just makes things stupid-simple, such as with its built-in automatic admin interface. Yet one thing it did not provide was an optional post-preview, where you could see exactly what your post will look like once it is live without others being able to see it.

For me this was a must-have feature. So I quickly thought up a stupid-simple way to add admin previews.

This technique works with or without newforms-admin and is insanely easy to implement.

This requires a general understanding of Django’s generic views. It also requires that you have a model that you want to preview. This model must have some kind of ‘draft’ status that is not shown on your live site, but is saved in the database.

So, lets say you have a model called Article. To add a preview for each article:

  • Add a generic object_detail view to your app’s views.py:

       from django.contrib.admin.views.decorators import staff_member_required
       from django.views.generic.list_detail import object_detail
       from your_app.models import Article
    

    @staff_member_required def preview(request, object_id): return object_detail(request, object_id=object_id, queryset=Article.objects.all(), template_object_name = 'article', )

    That @staffmemberrequired ensures that only people logged into your admin and designated a staff member for your site can see your article’s preview before it is live. The rest is just a generic object_detail view named ‘preview’.

  • Add a line to your app’s urls.py, above your admin url line:

    url(r'^admin/your_app/article/(?P<object_id>[0-9]+)/preview/$',
       'your_app.views.preview'),

  • You don’t actually have to add a template for the view if your project already has an object_detail template (named article_detail.html in this case). The generic view will grab this same template, and you’ll be able to see exactly what your post will look like on your live site.

  • Lastly, add a template to: /templates/admin/your_app/article/change_form.html. Paste this into that template:

       {% extends "admin/change_form.html" %} {% load i18n %}
        {% block object-tools %}
        {% if change %}{% if not is_popup %}
          <ul class="object-tools">
            <li><a href="history/" class="historylink">
                {% trans "History" %}</a></li>
            <li><a href="preview/" class="viewsitelink" target="_blank">
                {% trans "View preview" %}</a></li>
          {% if has_absolute_url %}<li>
            <a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">
                {% trans "View on site" %}</a></li>{% endif%}
          </ul>
        {% endif %}{% endif %}
        {% endblock %}

The beauty of that ‘View preview’ link is it will only appear on the change form for the appropriate model (in this case, Article) and only once the article has been saved to the database (so you must save it as a draft first).

So after you restart your server, every time you save an article as a draft, you’ll be able to click a button and see exactly what your post will look like to the world, without the world having to see it. :)

Posted July 28, 2008
Tags
django
Comment
8 comments
Navigate
rewind / forward

Comments!

  1. matt 7.28.08 / 8p.m.

    wow awesome

  2. David Reynolds 7.29.08 / 4a.m.

    Wow, thanks for the nice simple explanation of how to do this.

    Also, I love your design!

  3. Brian Luft 7.29.08 / 6p.m.

    Great tip - thank you for sharing!

    Your site design is pretty keen too!

  4. Simon Scarfe 7.29.08 / 6p.m.

    I did the same thing in a very similar way. However, I added the staff_member business to the page view function itself (if exists and not live and user is staff_member or some such nonsense) and stuck a massive red heading across the top, saying "THIS IS IN DRAFT, YO!". Works wonderfully.

    Gorgeous page design, btw. That hide show at the top for other bits and pieces, could be something that I one day rip off remorselessly.

  5. Julien Phalip 7.29.08 / 10p.m.

    Thanks for the great tip! Just a quick note though. You don't need to copy the entire content of the change_form template. Instead, you can extend it and only modify the bit you're interested in. See below:

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

    {% block object-tools %} {% if change %}{% if not is_popup %}

    {% endif %}{% endif %} {% endblock %}

  6. Julien Phalip 7.29.08 / 10p.m.

    Oops, the html did render properly in my previous comment. But you get the point, you can just modify the {% block object-tools %}. ;)

  7. Liz 7.30.08 / 12a.m.

    @ Julien -- Thanks for reminding me! I was in a bit of a rush to get this out, and totally forgot about blocks! ;)

  8. Mark Meyer 8.5.08 / 1a.m.

    Thanks for the tip.

Comments are closed for this article.

twitter

got my two tickets to see @conanobrien in june! weeee! about 6 hours, 58 minutes ago

tumbling other tumbles +-
words i didn't write +-

you can’t get to heaven in your sunday best

when the night before they were calling it

your cocktail dress

(sleater-kinney)

flickr +-
last.fm +-
delicious +-