Django backoffice config

Version 8 (Etienne Pallier, 03/25/2016 03:33 pm)

1 2 Etienne Pallier
h1. CONFIGURATION of the Django Back Office (administration interface)
2 1 Etienne Pallier
3 1 Etienne Pallier
4 3 Etienne Pallier
{{>toc}}
5 3 Etienne Pallier
6 3 Etienne Pallier
7 1 Etienne Pallier
---
8 1 Etienne Pallier
9 1 Etienne Pallier
h3. Back Office setup
10 1 Etienne Pallier
11 1 Etienne Pallier
 * Prerequisites in src/pyros/settings.py :
12 1 Etienne Pallier
13 1 Etienne Pallier
    * INSTALLED_APPS must (at least) contain :
14 1 Etienne Pallier
15 1 Etienne Pallier
        * django.contrib.admin
16 1 Etienne Pallier
        * django.contrib.auth
17 1 Etienne Pallier
        * django.contrib.contenttypes
18 1 Etienne Pallier
        * django.contrib.sessions
19 1 Etienne Pallier
20 4 Etienne Pallier
    * MIDDLEWARE_CLASSES must (at least) contain :
21 1 Etienne Pallier
22 1 Etienne Pallier
        * django.contrib.sessions.middleware.SessionMiddleware
23 1 Etienne Pallier
        * django.middleware.common.CommonMiddleware
24 1 Etienne Pallier
        * django.contrib.auth.middleware.AuthenticationMiddleware
25 1 Etienne Pallier
26 1 Etienne Pallier
 * At least one 'python manage.py migrate' must have been executed
27 1 Etienne Pallier
28 1 Etienne Pallier
 * Create a superuser for the administration :
29 1 Etienne Pallier
30 1 Etienne Pallier
<pre>
31 1 Etienne Pallier
$ python manage.py createsuperuser
32 1 Etienne Pallier
</pre>
33 1 Etienne Pallier
34 1 Etienne Pallier
* For each app of the project, fill the admin.py file :
35 1 Etienne Pallier
36 1 Etienne Pallier
<pre>
37 1 Etienne Pallier
from django.contrib import admin
38 5 Etienne Pallier
from app.models import Model1, Model2, ..., ModelN
39 5 Etienne Pallier
(or "from app.models import *")
40 1 Etienne Pallier
41 1 Etienne Pallier
admin.site.register(Model1)
42 1 Etienne Pallier
admin.site.register(Model2)
43 5 Etienne Pallier
...
44 5 Etienne Pallier
admin.site.register(ModelN)
45 1 Etienne Pallier
</pre>
46 5 Etienne Pallier
47 5 Etienne Pallier
So, for our application "pyrosapp", we have:
48 5 Etienne Pallier
<pre>
49 5 Etienne Pallier
from pyrosapp.models import *
50 5 Etienne Pallier
...
51 5 Etienne Pallier
</pre>
52 5 Etienne Pallier
53 1 Etienne Pallier
54 1 Etienne Pallier
*Reminder* : each application must be registered in the settings.py INSTALLED_APPS variable.
55 1 Etienne Pallier
56 1 Etienne Pallier
* For each model in models.py, add a '__str__()' method in order to identify the object on the back office. Example :
57 1 Etienne Pallier
58 1 Etienne Pallier
<pre>
59 1 Etienne Pallier
class UserLevel(models.Model):
60 1 Etienne Pallier
    name = models.CharField(max_length=45, blank=True, null=True)
61 1 Etienne Pallier
    desc = models.TextField(blank=True, null=True)
62 1 Etienne Pallier
    priority = models.IntegerField(blank=True, null=True)
63 1 Etienne Pallier
    quota = models.FloatField(blank=True, null=True)
64 1 Etienne Pallier
65 1 Etienne Pallier
    class Meta:
66 1 Etienne Pallier
        managed = True
67 1 Etienne Pallier
        db_table = 'userlevel'
68 1 Etienne Pallier
69 1 Etienne Pallier
    def __str__(self):
70 1 Etienne Pallier
        return (str(self.name))
71 1 Etienne Pallier
</pre>
72 1 Etienne Pallier
73 1 Etienne Pallier
*Naming convention* : Use self.name when possible, the creation time/date otherwise. Example :
74 1 Etienne Pallier
75 1 Etienne Pallier
<pre>
76 1 Etienne Pallier
class SiteWatch(models.Model):
77 1 Etienne Pallier
    updated = models.DateTimeField(blank=True, null=True)
78 1 Etienne Pallier
    lights = models.CharField(max_length=45, blank=True, null=True)
79 1 Etienne Pallier
    dome = models.CharField(max_length=45, blank=True, null=True)
80 1 Etienne Pallier
    doors = models.CharField(max_length=45, blank=True, null=True)
81 1 Etienne Pallier
    temperature = models.FloatField(blank=True, null=True)
82 1 Etienne Pallier
83 1 Etienne Pallier
    class Meta:
84 1 Etienne Pallier
        managed = True
85 1 Etienne Pallier
        db_table = 'sitewatch'
86 1 Etienne Pallier
87 1 Etienne Pallier
    def __str__(self):
88 1 Etienne Pallier
        return (str(self.updated))
89 1 Etienne Pallier
</pre>
90 1 Etienne Pallier
91 1 Etienne Pallier
---
92 1 Etienne Pallier
93 1 Etienne Pallier
h3. Adaptation of the one-to-many and many-to-many display
94 1 Etienne Pallier
95 7 Etienne Pallier
*1) The one-to-many relationships*
96 1 Etienne Pallier
97 7 Etienne Pallier
The one-to-many relationships are the following (One.many format) :
98 7 Etienne Pallier
99 1 Etienne Pallier
    * Schedule.sequences
100 1 Etienne Pallier
    * Request.sequences
101 1 Etienne Pallier
    * Sequence.albums
102 1 Etienne Pallier
    * Album.plans
103 1 Etienne Pallier
    * Plan.images
104 1 Etienne Pallier
    * Telescope.detectors
105 1 Etienne Pallier
    * Detector.filters
106 1 Etienne Pallier
    * NrtAnalysis.images
107 1 Etienne Pallier
    * Filter.plans
108 1 Etienne Pallier
    * Detector.albums
109 1 Etienne Pallier
    * UserLevel.users
110 1 Etienne Pallier
    * Country.users
111 1 Etienne Pallier
    * ScientificProgram.requests
112 1 Etienne Pallier
    * User.requests
113 1 Etienne Pallier
    * StrategyObs.alerts
114 1 Etienne Pallier
    * SequenceType.sequences
115 1 Etienne Pallier
116 6 Etienne Pallier
* For each "many", create a new class in admin.py just after the imports, following these examples :
117 6 Etienne Pallier
118 1 Etienne Pallier
<pre>
119 1 Etienne Pallier
120 1 Etienne Pallier
For Schedule.sequences, Request.sequences and Sequentype.sequences, we will need :
121 1 Etienne Pallier
122 1 Etienne Pallier
class SequenceInline(admin.TabularInline):
123 1 Etienne Pallier
    model = Sequence
124 1 Etienne Pallier
    fields = ("name",)
125 1 Etienne Pallier
    show_change_link = True
126 1 Etienne Pallier
127 1 Etienne Pallier
128 1 Etienne Pallier
For Sequence.albums and Detector.albums, we will need :
129 1 Etienne Pallier
130 1 Etienne Pallier
class AlbumInline(admin.TabularInline):
131 1 Etienne Pallier
    model = Album
132 1 Etienne Pallier
    fields = ("name",)
133 1 Etienne Pallier
    show_change_link = True
134 1 Etienne Pallier
135 1 Etienne Pallier
136 1 Etienne Pallier
For StrategyObs.alerts, we will need :
137 1 Etienne Pallier
138 1 Etienne Pallier
class AlertInline(admin.TabularInline):
139 1 Etienne Pallier
    model = Alert
140 1 Etienne Pallier
    fields = ("request.name",) # there is no 'name' attribute in the Alert model
141 1 Etienne Pallier
    show_change_link = True
142 1 Etienne Pallier
143 1 Etienne Pallier
</pre>
144 1 Etienne Pallier
145 1 Etienne Pallier
* For each "One", declare a new class in admin.py, just after the "Inlines" class declaration, as done in the following examples :
146 1 Etienne Pallier
147 1 Etienne Pallier
<pre>
148 1 Etienne Pallier
For Request.sequences :
149 1 Etienne Pallier
150 1 Etienne Pallier
class RequestAdmin(admin.ModelAdmin):
151 1 Etienne Pallier
    inlines = [
152 1 Etienne Pallier
	SequenceInline,
153 1 Etienne Pallier
    ]
154 1 Etienne Pallier
155 1 Etienne Pallier
For Detector.filters and Detector.albums :
156 1 Etienne Pallier
157 1 Etienne Pallier
class DetectorAdmin(admin.ModelAdmin):
158 1 Etienne Pallier
    inlines = [
159 8 Etienne Pallier
        FilterInline,
160 1 Etienne Pallier
        AlbumInline,
161 1 Etienne Pallier
    ]
162 1 Etienne Pallier
163 1 Etienne Pallier
</pre>
164 1 Etienne Pallier
165 1 Etienne Pallier
166 7 Etienne Pallier
*2) The many-to-many relationships*
167 7 Etienne Pallier
168 7 Etienne Pallier
The many-to-many relationships are the following :
169 1 Etienne Pallier
170 1 Etienne Pallier
    * ScientificProgram - User
171 1 Etienne Pallier
    * ScheduleHistory - Sequence
172 1 Etienne Pallier
173 1 Etienne Pallier
* For each many-to-many relationship, declare a new "Inline" class in admin.py just after the imports, like this :
174 1 Etienne Pallier
175 1 Etienne Pallier
<pre>
176 1 Etienne Pallier
For ScientificProgram - User :
177 1 Etienne Pallier
178 1 Etienne Pallier
class UserAndSPInline(admin.TabularInline):
179 1 Etienne Pallier
    model = ScientificProgram.users.through
180 1 Etienne Pallier
181 1 Etienne Pallier
182 1 Etienne Pallier
For ScheduleHistory - Sequence
183 1 Etienne Pallier
184 1 Etienne Pallier
class SequenceAndSHInline(admin.TabularInline):
185 1 Etienne Pallier
    model = ScheduleHistory.sequences.through
186 1 Etienne Pallier
187 1 Etienne Pallier
</pre>
188 1 Etienne Pallier
189 1 Etienne Pallier
+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.
190 1 Etienne Pallier
191 1 Etienne Pallier
* For each many-to-many relationship, declare two new classes in admin.py, just after the inlines, like in the following examples :
192 1 Etienne Pallier
193 1 Etienne Pallier
<pre>
194 1 Etienne Pallier
For the ScheduleHistory - Sequence relationship :
195 1 Etienne Pallier
196 1 Etienne Pallier
class ScheduleHistoryAdmin(admin.ModelAdmin):
197 1 Etienne Pallier
    inlines = [
198 1 Etienne Pallier
        SequenceAndSHInline,
199 1 Etienne Pallier
    ]
200 1 Etienne Pallier
    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
201 1 Etienne Pallier
202 1 Etienne Pallier
class SequenceAdmin(admin.ModelAdmin):
203 1 Etienne Pallier
    inlines = [
204 1 Etienne Pallier
        AlbumInline,        # This is the Inline for the one-to-many relationship Sequence.albums
205 1 Etienne Pallier
        SequenceAndSHInline,                                                                
206 1 Etienne Pallier
    ]
207 1 Etienne Pallier
208 1 Etienne Pallier
For the ScientificProgram - User relationship :
209 1 Etienne Pallier
210 1 Etienne Pallier
class ScientificProgramAdmin(admin.ModelAdmin):
211 1 Etienne Pallier
    inlines = [
212 1 Etienne Pallier
        RequestInline,
213 1 Etienne Pallier
	UserAndSPInline,                                                                         
214 1 Etienne Pallier
    ]
215 1 Etienne Pallier
    exclude = ('users',) # Same as ScheduleHistory                                                                         
216 1 Etienne Pallier
217 1 Etienne Pallier
class UserAdmin(admin.ModelAdmin):
218 1 Etienne Pallier
    inlines = [
219 1 Etienne Pallier
	RequestInline,   # This is the Inline for the one-to-many relationship User.requests
220 1 Etienne Pallier
        UserAndSPInline,                                                                    
221 1 Etienne Pallier
    ]
222 1 Etienne Pallier
223 1 Etienne Pallier
</pre>
224 1 Etienne Pallier
225 1 Etienne Pallier
* For each ModelAdmin class in the admin.py, change the registering line
226 1 Etienne Pallier
227 1 Etienne Pallier
<pre>
228 1 Etienne Pallier
admin.site.register(Album)
229 1 Etienne Pallier
</pre>
230 1 Etienne Pallier
231 1 Etienne Pallier
to
232 1 Etienne Pallier
233 1 Etienne Pallier
<pre>
234 1 Etienne Pallier
admin.site.register(Album, AlbumAdmin)
235 1 Etienne Pallier
</pre>