« Previous - Version 7/11 (diff) - Next » - Current version
Etienne Pallier, 03/25/2016 03:32 pm


CONFIGURATION of the Django Back Office (administration interface)


Back Office setup

  • Prerequisites in src/pyros/settings.py :
    • INSTALLED_APPS must (at least) contain :
      • django.contrib.admin
      • django.contrib.auth
      • django.contrib.contenttypes
      • django.contrib.sessions
    • MIDDLEWARE_CLASSES must (at least) contain :
      • django.contrib.sessions.middleware.SessionMiddleware
      • django.middleware.common.CommonMiddleware
      • django.contrib.auth.middleware.AuthenticationMiddleware
  • At least one 'python manage.py migrate' must have been executed
  • Create a superuser for the administration :
$ python manage.py createsuperuser
  • For each app of the project, fill the admin.py file :
from django.contrib import admin
from app.models import Model1, Model2, ..., ModelN
(or "from app.models import *")

admin.site.register(Model1)
admin.site.register(Model2)
...
admin.site.register(ModelN)

So, for our application "pyrosapp", we have:

from pyrosapp.models import *
...

Reminder : each application must be registered in the settings.py INSTALLED_APPS variable.

  • For each model in models.py, add a '__str__()' method in order to identify the object on the back office. Example :
class UserLevel(models.Model):
    name = models.CharField(max_length=45, blank=True, null=True)
    desc = models.TextField(blank=True, null=True)
    priority = models.IntegerField(blank=True, null=True)
    quota = models.FloatField(blank=True, null=True)

    class Meta:
        managed = True
        db_table = 'userlevel'

    def __str__(self):
        return (str(self.name))

Naming convention : Use self.name when possible, the creation time/date otherwise. Example :

class SiteWatch(models.Model):
    updated = models.DateTimeField(blank=True, null=True)
    lights = models.CharField(max_length=45, blank=True, null=True)
    dome = models.CharField(max_length=45, blank=True, null=True)
    doors = models.CharField(max_length=45, blank=True, null=True)
    temperature = models.FloatField(blank=True, null=True)

    class Meta:
        managed = True
        db_table = 'sitewatch'

    def __str__(self):
        return (str(self.updated))

Adaptation of the one-to-many and many-to-many display

1) The one-to-many relationships

The one-to-many relationships are the following (One.many format) :

  • Schedule.sequences
  • Request.sequences
  • Sequence.albums
  • Album.plans
  • Plan.images
  • Telescope.detectors
  • Detector.filters
  • NrtAnalysis.images
  • Filter.plans
  • Detector.albums
  • UserLevel.users
  • Country.users
  • ScientificProgram.requests
  • User.requests
  • StrategyObs.alerts
  • SequenceType.sequences
  • For each "many", create a new class in admin.py just after the imports, following these examples :

For Schedule.sequences, Request.sequences and Sequentype.sequences, we will need :

class SequenceInline(admin.TabularInline):
    model = Sequence
    fields = ("name",)
    show_change_link = True

For Sequence.albums and Detector.albums, we will need :

class AlbumInline(admin.TabularInline):
    model = Album
    fields = ("name",)
    show_change_link = True

For StrategyObs.alerts, we will need :

class AlertInline(admin.TabularInline):
    model = Alert
    fields = ("request.name",) # there is no 'name' attribute in the Alert model
    show_change_link = True

  • For each "One", declare a new class in admin.py, just after the "Inlines" class declaration, as done in the following examples :
For Request.sequences :

class RequestAdmin(admin.ModelAdmin):
    inlines = [
    SequenceInline,
    ]

For Detector.filters and Detector.albums :

class DetectorAdmin(admin.ModelAdmin):
    inlines = [
    FilterInline,
        AlbumInline,
    ]

2) The many-to-many relationships

The many-to-many relationships are the following :

  • ScientificProgram - User
  • ScheduleHistory - Sequence
  • For each many-to-many relationship, declare a new "Inline" class in admin.py just after the imports, like this :
For ScientificProgram - User :

class UserAndSPInline(admin.TabularInline):
    model = ScientificProgram.users.through

For ScheduleHistory - Sequence

class SequenceAndSHInline(admin.TabularInline):
    model = ScheduleHistory.sequences.through

Note : The order in the line "model = ScientificProgram.users.through" is very important : the first model (ScientificProgram) is the one in which is declared the ManyToManyField relationship.

  • For each many-to-many relationship, declare two new classes in admin.py, just after the inlines, like in the following examples :
For the ScheduleHistory - Sequence relationship :

class ScheduleHistoryAdmin(admin.ModelAdmin):
    inlines = [
        SequenceAndSHInline,
    ]
    exclude = ('sequences',) # ScheduleHistory declares the ManyToManyField, and we want to replace its display in the back office, so we won't display the default field

class SequenceAdmin(admin.ModelAdmin):
    inlines = [
        AlbumInline,        # This is the Inline for the one-to-many relationship Sequence.albums
        SequenceAndSHInline,                                                                
    ]

For the ScientificProgram - User relationship :

class ScientificProgramAdmin(admin.ModelAdmin):
    inlines = [
        RequestInline,
    UserAndSPInline,                                                                         
    ]
    exclude = ('users',) # Same as ScheduleHistory                                                                         

class UserAdmin(admin.ModelAdmin):
    inlines = [
    RequestInline,   # This is the Inline for the one-to-many relationship User.requests
        UserAndSPInline,                                                                    
    ]

  • For each ModelAdmin class in the admin.py, change the registering line
admin.site.register(Album)

to

admin.site.register(Album, AlbumAdmin)