Admin Interface

Many web applications ship with an “admin area”, where priveleged users can view and modify content. By introspecting your application’s models, flask-peewee can provide you with straightforward, easily-extensible forms for managing your application content.

Here’s a screen-shot of the admin dashboard:

_images/fp-admin.jpg

Getting started

To get started with the admin, there are just a couple steps:

  1. Instantiate an Auth backend for your project – this component is responsible for providing the security for the admin area

    from flask import Flask
    
    from flaskext.auth import Auth
    from flaskext.db import Database
    
    app = Flask(__name__)
    db = Database(app)
    
    # needed for authentication
    auth = Auth(app, db)
    
  2. Instantiate an Admin object

    # continued from above...
    from flaskext.admin import Admin
    
    admin = Admin(app, auth)
    
  3. Register any ModelAdmin or AdminPanel objects you would like to expose via the admin

    # continuing... assuming "Blog" and "Entry" models
    admin.register(Blog) # register "Blog" with vanilla ModelAdmin
    admin.register(Entry, EntryAdmin) # register "Entry" with a custom ModelAdmin subclass
    
    # assume we have an "AdminPanel" called "NotePanel"
    admin.register_panel('Notes', NotePanel)
    
  4. Call Admin.setup(), which registers the admin blueprint and configures the urls

    # after all models and panels are registered, configure the urls
    admin.setup()
    

Note

for a complete example, check the Example App which ships with the project

Components of the Admin

The admin area is composed of three main components:

  1. ModelAdmin instances, which expose create/edit/delete functionality for peewee models
  2. AdminPanel instances, which appear in the dashboard and provide any additional functionality
  3. Admin which serves as a central registry for ModelAdmin and AdminPanel instances

ModelAdmin

Screenshot showing a typical ModelAdmin – this one exposing Message objects. Currently the list of messages is filtered to only list those by the user “coleifer”.

_images/fp-model-admin-cropped.jpg

Typical usage:

admin = Admin(app, auth)

class Message(db.Model):
    user = ForeignKeyField(User)
    content = TextField()
    pub_date = DateTimeField(default=datetime.datetime.now)

    def __unicode__(self):
        return '%s: %s' % (self.user, self.content)

class MessageAdmin(ModelAdmin):
    columns = ('user', 'content', 'pub_date',)


admin.register(Message, MessageAdmin)
class ModelAdmin

Class that determines how a peewee Model is exposed in the admin area. Provides a way of encapsulating model-specific configuration and behaviors.

columns

What columns should be displayed in the list index. By default if no columns are specified the Model‘s __unicode__() will be used.

If a column is a model field, it will be “sortable”.

class EntryAdmin(ModelAdmin):
    columns = ['title', 'pub_date', 'blog']

Note

columns can be either attributes of the model or callables on the model instance, though they will be called with no parameters.

paginate_by

How many records to paginate by when viewing lists of models, defaults to 20

get_query()
Return type:A SelectQuery that represents the list of objects to expose

Useful in the event that you would like to limit the objects shown via the admin.

class UserAdmin(ModelAdmin):
    def get_query():
        # ask the auth system for the currently logged-in user
        current_user = self.auth.get_logged_in_user()

        # if they are not a superuser, only show them their own
        # account in the admin
        if not current_user.is_superuser:
            return User.filter(id=current_user.id)

        # otherwise, show them all users
        return User.select()
get_object(pk)
Return type:The model instance with the given pk, raising a DoesNotExist in the event the model instance does not exist.
get_form()

Provides a useful extension point in the event you want to define custom fields or custom validation behavior.

Return type:A wtf-peewee Form subclass that will be used when adding or editing model instances in the admin.
save_model(instance, form, adding=False)
Parameters:
  • instance – an unsaved model instance
  • form – a validated form instance
  • adding – boolean to indicate whether we are adding a new instance or saving an existing

Method responsible for persisting changes to the database. Called by both the add and the edit views.

Here is an example from the default auth.User ModelAdmin, in which the password is displayed as a sha1, but if the user is adding or edits the existing password, it re-hashes:

def save_model(self, instance, form, adding=False):
    orig_password = instance.password

    user = super(UserAdmin, self).save_model(instance, form, adding)

    if orig_password != form.password.data:
        user.set_password(form.password.data)
        user.save()

    return user
get_urls()

Useful as a hook for extending ModelAdmin functionality with additional urls.

Return type:tuple of 2-tuples consisting of a mapping between url and view
get_url_name(name)

Since urls are namespaced, this function provides an easy way to get full urls to views provided by this ModelAdmin

AdminPanel

Screenshot showing some examples of AdminPanel instances. One of these exposes a form where administrators can post “notes”, the other showing some aggregate data on user signups and site activity:

_images/fp-panels.jpg

Typical usage:

# panel code

class NotePanel(AdminPanel):
    template_name = 'admin/notes.html'

    def get_urls(self):
        return (
            ('/create/', self.create),
        )

    def create(self):
        if request.method == 'POST':
            if request.form.get('message'):
                Note.create(
                    user=auth.get_logged_in_user(),
                    message=request.form['message'],
                )
        next = request.form.get('next') or self.dashboard_url()
        return redirect(next)

    def get_context(self):
        return {
            'note_list': Note.select().order_by(('created_date', 'desc')).paginate(1, 3)
        }

admin.register_panel('Notes', NotePanel)
<!-- template code -->
{% extends "admin/panels/default.html" %}

{% block panel_content %}
  {% for note in note_list %}
    <p>{{ note.user.username }}: {{ note.message }}</p>
  {% endfor %}
  <form method="post" action="{{ url_for(panel.get_url_name('create')) }}">
    <input type="hidden" value="{{ request.url }}" />
    <p><textarea name="message"></textarea></p>
    <p><button type="submit" class="small">Save</button></p>
  </form>
{% endblock %}
class AdminPanel

Class that provides a simple interface for providing arbitrary extensions to the admin. These are displayed as “panels” on the admin dashboard with a customizable template. They may additionally, however, define any views and urls.

template_name

What template to use to render the panel in the admin dashboard, defaults to 'admin/panels/default.html'.

get_urls()

Mapping of urls and views that are provided by this panel.

Return type:Returns a tuple of 2-tuples mapping url to view
get_url_name(name)

Since urls are namespaced, this function provides an easy way to get full urls to views provided by this panel

Parameters:name – string representation of the view function whose url you want
Return type:String representing url
<!-- taken from example -->
<!-- will return something like /admin/notes/create/ -->
{{ url_for(panel.get_url_name('create')) }}
get_template_name()

Return the template used to render this panel in the dashboard. By default simply returns the template stored under AdminPanel.template_name.

get_context()

Return the context to be used when rendering the dashboard template.

Return type:Dictionary
render()

Render the panel template with the context – this is what gets displayed in the admin dashboard.

The Admin Class

class Admin

Class used to expose an admin area at a certain url in your application.

__init__(app, auth[, blueprint_factory[, template_helper[, prefix]]])
Parameters:
  • app – flask application to bind admin to
  • authAuth instance which will provide authentication
  • blueprint_factory – an object that will create the BluePrint used by the admin
  • template_helper – a subclass of AdminTemplateHelper that provides helpers and context to used by the admin templates
  • prefix – url to bind admin to, defaults to /admin
register(model[, admin_class=ModelAdmin])
Parameters:
  • model – peewee model to expose via the admin
  • admin_classModelAdmin or subclass to use with given model
register_panel(title, panel)
Parameters:
  • title – identifier for panel, example might be “Site Stats”
  • panel – subclass of AdminPanel to display
setup()

Configures urls for models and panels, then registers blueprint.

Warning

call this after registering your models and panels

check_user_permission(user)
Parameters:user – the currently logged-in user, exposed by the Auth instance

Check whether the given user has permission to access to the admin area. The default implementation simply checks whether the admin field is checked.

def check_user_permission(self, user):
    return user.admin
Return type:Boolean
get_urls()

Get a tuple of 2-tuples mapping urls to view functions that will be exposed by the admin. The default implementation looks like this:

def get_urls(self):
    return (
        ('/', self.auth_required(self.index)),
    )

Table Of Contents

Previous topic

Database Wrapper

Next topic

Authentication

This Page