### Navigation

- index
- modules |
- next |
- previous |
- Camelot v0.1 documentation »
- Camelot Documentation contents »
- Camelot Documentation »

# Customizing the Admin classes

Release: | 0.1
Date: | July 02, 2010

The Admin classes are the classes that specify how objects should be visualized, they define the look, feel and behaviour of the Application. Most of the behaviour of the Admin classes can be tuned by changing their static attributes. This makes it easy to subclass a default Admin class and tune it to your needs.

Each elixir Entity that is visualized within Camelot has an associated Admin class which specifies how the entity or a list of entities should be visualized.

Those entities are subclasses of the EntityAdmin class in the module camelot/view/elixir_admin.

Usually the Admin class is bound to the Entity class by defining it as an inner class of the Entity class:

    class Movie(Entity):
      title = Field(Unicode(60), required=True)

      class Admin(EntityAdmin):
        name = 'Movies'
        list_display = ['title']

Most of the behaviour of the Admin class can be customized by changing the class attributes like name or list_display.

## ObjectAdmin

The base type of EntityAdmin, is ObjectAdmin, which specifies most of the class attributes that can be used to customize the interface.

class `camelot.admin.object_admin.``ObjectAdmin`(app_admin, entity)

  The ObjectAdmin class describes the interface that will be used to interact with objects of a certain class. The behaviour of this class and the resulting interface can be tuned by specifying specific class attributes:

  `verbose_name`

  A human-readable name for the object, singular

  verbose_name = ‘movie’

  If this isn’t given, the class name will be used

  `verbose_name_plural`

  A human-readable name for the object, plural

  verbose_name_plural = ‘movies’

  If this isn’t given, Camelot will use verbose_name + “s”

  `list_display`

  a list with the fields that should be displayed in a table view

  `form_display`

  a list with the fields that should be displayed in a form view, defaults to the same fields as those specified in list_display

  class Admin(EntityAdmin):
    form_display = [‘title’, ‘rating’, ‘cover’]

  instead of telling which forms to display. It is also possible to define the form itself

  from camelot.view.forms import Form, TabForm, WidgetOnlyForm, HBoxForm

  class Admin(EntityAdmin):
    form_display = TabForm([
      (‘Movie’, Form([
        HBoxForm([[‘title’, ‘rating’], WidgetOnlyForm(‘cover’)]), ‘short_description’, ‘releasedate’, ‘director’, ‘script’, ‘genre’, ‘description’, ‘tags’], scrollbars=True)),

      (‘Cast’, WidgetOnlyForm(‘cast’))

    ])

  `list_filter`

  A list of fields that should be used to generate filters for in the table view. If the field named is a one2many, many2one or many2many field, the field name should be followed by a field name of the related entity

  class Project(Entity):

    oranization = OneToMany(‘Organization’) name = Field(Unicode(50))

    class Admin(EntityAdmin):
      list_display = [‘organization’] list_filter = [‘organization.name’]
  `list_search`

  A list of fields that should be searched when the user enters something in the search box in the table view. By default only character fields are searched. For use with one2many, many2one or many2many fields, the same rules as for the list_filter attribute apply

  `confirm_delete`

  Indicates if the deletion of an object should be confirmed by the user, defaults to False. Can be set to either True, False, or the message to display when asking confirmation of the deletion.

  `form_size`

  a tuple indicating the size of a form view, defaults to (700,500)

  `form_actions`

  Actions to be accessible by pushbuttons on the side of a form, a list of tuples (button_label, action_function) where action_function takes as its single argument, a method that returns the the object that was displayed by the form when the button was pressed:

  class Admin(EntityAdmin):
    form_actions = [(‘Foo’, lamda o_getter:print ‘foo’)]
  `field_attributes`

  A dictionary specifying for each field of the model some additional attributes on how they should be displayed. All of these attributes are propagated to the constructor of the delegate of this field:

  class Movie(Entity):

    title = Field(Unicode(50))

    class Admin(EntityAdmin):
      list_display = [‘title’] field_attributes = dict(title=dict(editable=False))

  Other field attributes process by the admin interface are:

  `name`

  The name of the field used, this defaults to the name of the attribute

  `target`

  In case of relation fields, specifies the class that is at the other end of the relation. Defaults to the one found by introspection.

  `admin`

  In case of relation fields, specifies the admin class that is to be used to visualize the other end of the relation. Defaults to the default admin class of the target class.

  `model`

  The QAbstractItemModel class to be used to display collections of this object, defaults to a CollectionProxy

  `confirm_delete`

  set to True if the user should get a confirmation dialog before deleting data, defaults to False

  `TableView`

  The QWidget class to be used when a table view is needed

Note

While EntityAdmin can only be used for classes that are mapped by Sqlalchemy, ObjectAdmin can be used for plain old python objects as well.

## EntityAdmin

EntityAdmin is a specialization of ObjectAdmin, to be used for classes that are mapped by Sqlalchemy. EntityAdmin will use introspection to determine field types and assign according delegates and editors.

## Form View Actions

Form actions are objects that can be put in the form_actions list of the object admin interfaces. Those actions then appear on the form and can be executed by the end users. The most convenient method to create custom actions is to subclass FormAction and implement a custom run method

    class MyAction(FormAction):

      def run(self, entity_getter):
        print 'Hello World'

    class Movie(Entity):
      title = Field(Unicode(60), required=True)

      Admin(EntityAdmin):
        list_display = ['title']
        form_actions = [MyAction('Hello')]

Several subclasses of FormAction exist to provide common use cases such as executing a function in the model thread or printing a report.

To customize the look of the action button on the form, the render method should be overwritten.

### Printing reports in the form view

class `camelot.admin.form_action.``PrintHtmlFormAction`(name, icon=Icon('tango/16x16/actions/document-print.png'))

  Create an action for a form that pops up a print preview for generated html. Overwrite the html function to customize the html that should be shown:

      class PrintMovieAction(PrintHtmlFormAction):

        def html(self, movie):
          html = '<h1>' + movie.title + '</h1>'
          html += movie.description
        return html

      class Movie(Entity):
        title = Field(Unicode(60), required=True)
        description = Field(camelot.types.RichText)

        class Admin(EntityAdmin):
          list_display = ['title', 'description']
          form_actions = [PrintMovieAction('summary')]

  will put a print button on the form :

  the rendering of the html can be customised using the HtmlDocument attribute :

  `HtmlDocument`

  the class used to render the html, by default this is a QTextDocument, but a QtWebKit.QWebView can be used as well.

## Validators

Before an object is written to the database it needs to be validated, and the user needs to be informed in case the object is not valid.

By default Camelot does some introspection on the model to check the validity of an object, to make sure it will be able to write the object to the database.

But this might not be enough. If more validation is needed, a custom Validator class can be defined. The default EntityValidator class is located in camelot/admin/validator/entity_validator. This class can be subclassed to create a custom validator. The new class should then be bound to the Admin class :

>     from camelot.admin.validator.entity_validator import EntityValidator
>     from camelot.admin.entity_admin import EntityAdmin

>     class PersonValidator(EntityValidator):

>         def objectValidity(self, entity_instance):
>             messages = super(PersonValidator,self).objectValidity(entity_instance)
>             if (not entity_instance.first_name) or (len(entity_instance.first_name) < 3):
>                 messages.append("A person's first name should be at least 2 characters long")
>             return messages

>     class Admin(EntityAdmin):
>         verbose_name = 'Person'
>         list_display = ['first_name', 'last_name']
>         validator = PersonValidator

Its most important method is objectValidity, which takes an object as argument and should return a list of strings explaining why the object is invalid. These strings will then be presented to the user.

Notice that this method will always get called outside of the GUI thread, so the call will never block the GUI.

When the user tries to leave a form in an invalid state, a platform dependent dialog box will appear.

## ApplicationAdmin

class `camelot.admin.application_admin.``ApplicationAdmin`

  The Application Admin class defines how the application should look like, it also ties python classes to their associated admin classes. It’s behaviour can be steered by overwriting its static attributes or it’s methods :

  `name`

  The name of the application, as it will appear in the title of the main window.

  `sections`

  A list containing the various sections that should appear in the left panel of the mainwindow.

  `backup_mechanism`

  A subclass of camelot.core.backup.BackupMechanism that enables the application to perform backups an restores.

      from camelot.view.art import Icon
      from camelot.admin.application_admin import ApplicationAdmin
      from camelot.admin.section import Section

      class MyApplicationAdmin(ApplicationAdmin):

        name = 'Camelot Video Store'

        def get_sections(self):
          from camelot.model.memento import Memento
          from camelot.model.authentication import Person, Organization
          from camelot.model.i18n import Translation
          from example.model import Movie, Tag
          return [Section('movies',
                          Icon('tango/22x22/mimetypes/x-office-presentation.png'),
                          items = [Movie, Tag]),
                  Section('relation',
                          Icon('tango/22x22/apps/system-users.png'),
                          items = [Person, Organization]),
                  Section('configuration',
                          Icon('tango/22x22/categories/preferences-system.png'),
                          items = [Memento, Translation])
                  ]

### Navigation

- index
- modules |
- next |
- previous |
- Camelot v0.1 documentation »
- Camelot Documentation contents »
- Camelot Documentation »