Django backoffice config
Version 7 (Etienne Pallier, 03/25/2016 03:32 pm) → Version 8/11 (Etienne Pallier, 03/25/2016 03:33 pm)
h1. CONFIGURATION of the Django Back Office (administration interface)
{{>toc}}
---
h3. 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 :
<pre>
$ python manage.py createsuperuser
</pre>
* For each app of the project, fill the admin.py file :
<pre>
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)
</pre>
So, for our application "pyrosapp", we have:
<pre>
from pyrosapp.models import *
...
</pre>
*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 :
<pre>
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))
</pre>
*Naming convention* : Use self.name when possible, the creation time/date otherwise. Example :
<pre>
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))
</pre>
---
h3. 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 :
<pre>
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
</pre>
* For each "One", declare a new class in admin.py, just after the "Inlines" class declaration, as done in the following examples :
<pre>
For Request.sequences :
class RequestAdmin(admin.ModelAdmin):
inlines = [
SequenceInline,
]
For Detector.filters and Detector.albums :
class DetectorAdmin(admin.ModelAdmin):
inlines = [
FilterInline,
AlbumInline,
]
</pre>
*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 :
<pre>
For ScientificProgram - User :
class UserAndSPInline(admin.TabularInline):
model = ScientificProgram.users.through
For ScheduleHistory - Sequence
class SequenceAndSHInline(admin.TabularInline):
model = ScheduleHistory.sequences.through
</pre>
+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 :
<pre>
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,
]
</pre>
* For each ModelAdmin class in the admin.py, change the registering line
<pre>
admin.site.register(Album)
</pre>
to
<pre>
admin.site.register(Album, AlbumAdmin)
</pre>
{{>toc}}
---
h3. 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 :
<pre>
$ python manage.py createsuperuser
</pre>
* For each app of the project, fill the admin.py file :
<pre>
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)
</pre>
So, for our application "pyrosapp", we have:
<pre>
from pyrosapp.models import *
...
</pre>
*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 :
<pre>
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))
</pre>
*Naming convention* : Use self.name when possible, the creation time/date otherwise. Example :
<pre>
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))
</pre>
---
h3. 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 :
<pre>
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
</pre>
* For each "One", declare a new class in admin.py, just after the "Inlines" class declaration, as done in the following examples :
<pre>
For Request.sequences :
class RequestAdmin(admin.ModelAdmin):
inlines = [
SequenceInline,
]
For Detector.filters and Detector.albums :
class DetectorAdmin(admin.ModelAdmin):
inlines = [
FilterInline,
AlbumInline,
]
</pre>
*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 :
<pre>
For ScientificProgram - User :
class UserAndSPInline(admin.TabularInline):
model = ScientificProgram.users.through
For ScheduleHistory - Sequence
class SequenceAndSHInline(admin.TabularInline):
model = ScheduleHistory.sequences.through
</pre>
+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 :
<pre>
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,
]
</pre>
* For each ModelAdmin class in the admin.py, change the registering line
<pre>
admin.site.register(Album)
</pre>
to
<pre>
admin.site.register(Album, AlbumAdmin)
</pre>