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
- INSTALLED_APPS must (at least) contain :
- 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 readonly_fields = ("name",) fields = ("name",) show_change_link = True For Sequence.albums and Detector.albums, we will need : class AlbumInline(admin.TabularInline): model = Album readonly_fields = ("name",) fields = ("name",) show_change_link = True For StrategyObs.alerts, we will need : class AlertInline(admin.TabularInline): model = Alert readonly_fields = ("request_name",) # there is no 'name' attribute in the Alert model, so we use a custom method 'request_name' declared in the Alert model fields = ("request_name",) 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)