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>