Customization

While Grappelli is mainly about the look & feel of the Admin-Interface, it also adds some features.

Available Settings

GRAPPELLI_ADMIN_TITLE
The Site Title of your Admin-Interface. Change this instead of changing index.html

Collapsibles

Use the classes property in order to define collapsibles for a ModelAdmin or an InlineModelAdmin. Possible values are collapse open and collapse closed.

A ModelAdmin example:

class ModelOptions(admin.ModelAdmin):
    fieldsets = (
        ('', {
            'fields': ('title', 'subtitle', 'slug', 'pub_date', 'status',),
        }),
        ('Flags', {
            'classes': ('collapse closed',),
            'fields' : ('flag_front', 'flag_sticky', 'flag_allow_comments', 'flag_comments_closed',),
        }),
        ('Tags', {
            'classes': ('collapse open',),
            'fields' : ('tags',),
        }),
    )

An InlineModelAdmin example:

class NavigationItemInline(admin.StackedInline):
    classes = ('collapse open',)

Inline Sortables

New in Grappelli 1.3: Please see Release Notes.

For using drag/drop with Inlines, you need to add a PositiveIntegerField to your Model:

class MyInlineModel(models.Model):
    mymodel = models.ForeignKey(MyModel)
    # position field
    position = models.PositiveSmallIntegerField("Position")
    class Meta:
        ordering = ['position']

Now, define the sortable_field_name with your InlineModelAdmin:

class MyInlineModelOptions(admin.TabularInline):
    fields = (... , "position",)
    # define the sortable
    sortable_field_name = "position"

The inline-rows are being reordered based on the sortable-field (with a templatetag formsetsort). When submitting a form, the values of the sortable-field are re-indexed according to the position of each row. In case of errors (somewhere within the form), the position of inline-rows are being preserved. This applies to rows prepeared for deletion as well. Empty rows are moved to the end of the formset.

Note

The sortable-field will not automatically be hidden (use a Hidden Input Widget if needed). For continous position-numbers (in your database), use a PositionField (see django-positions) instead of the PositiveIntegerField.

Generic Relationships

Grappelli also adds the representation of an object for Generic Relations:

from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db import models

class MyModel(models.Model):
    # first generic relation
    content_type = models.ForeignKey(ContentType, blank=True, null=True, related_name="content_type")
    object_id = models.PositiveIntegerField(blank=True, null=True)
    content_object = generic.GenericForeignKey("content_type", "object_id")
    # second generic relation
    content_type_2 = models.ForeignKey(ContentType, blank=True, null=True, related_name="content_type_2")
    object_id_2 = models.PositiveIntegerField(blank=True, null=True)
    content_object_2 = generic.GenericForeignKey("content_type_2", "object_id_2")

Using TinyMCE

Copy tinymce_setup.js to your media-directory, adjust the setup (see TinyMCE Configuration) and add the necessary javascripts:

class Media:
    js = [
        '/media/admin/tinymce/jscripts/tiny_mce/tiny_mce.js',
        '/path/to/your/tinymce_setup.js',
    ]

Using TinyMCE with Inlines is a bit more tricky because of the hidden empty-form. You need to write a custom template and use the inline-callbacks to

  • onInit: remove TinyMCE instances from the the empty-form.
  • onAfterAdded: initialize TinyMCE instance(s) from the form.
  • onBeforeRemoved: remove TinyMCE instance(s) from the form.

Note

TinyMCE with Inlines is not supported by default.

Table Of Contents

Previous topic

Quick start guide

Next topic

Dashboard Setup

This Page