Django backoffice config

Version 5 (Etienne Pallier, 03/24/2016 06:20 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 1 Etienne Pallier
* The one-to-many relationships are the following (One.many format) :
96 1 Etienne Pallier
97 1 Etienne Pallier
    * Schedule.sequences
98 1 Etienne Pallier
    * Request.sequences
99 1 Etienne Pallier
    * Sequence.albums
100 1 Etienne Pallier
    * Album.plans
101 1 Etienne Pallier
    * Plan.images
102 1 Etienne Pallier
    * Telescope.detectors
103 1 Etienne Pallier
    * Detector.filters
104 1 Etienne Pallier
    * NrtAnalysis.images
105 1 Etienne Pallier
    * Filter.plans
106 1 Etienne Pallier
    * Detector.albums
107 1 Etienne Pallier
    * UserLevel.users
108 1 Etienne Pallier
    * Country.users
109 1 Etienne Pallier
    * ScientificProgram.requests
110 1 Etienne Pallier
    * User.requests
111 1 Etienne Pallier
    * StrategyObs.alerts
112 1 Etienne Pallier
    * SequenceType.sequences
113 1 Etienne Pallier
114 1 Etienne Pallier
* For each "many", create a new class in admin.py just after the imports, following these examples :
115 1 Etienne Pallier
116 1 Etienne Pallier
<pre>
117 1 Etienne Pallier
118 1 Etienne Pallier
For Schedule.sequences, Request.sequences and Sequentype.sequences, we will need :
119 1 Etienne Pallier
120 1 Etienne Pallier
class SequenceInline(admin.TabularInline):
121 1 Etienne Pallier
    model = Sequence
122 1 Etienne Pallier
    fields = ("name",)
123 1 Etienne Pallier
    show_change_link = True
124 1 Etienne Pallier
125 1 Etienne Pallier
126 1 Etienne Pallier
For Sequence.albums and Detector.albums, we will need :
127 1 Etienne Pallier
128 1 Etienne Pallier
class AlbumInline(admin.TabularInline):
129 1 Etienne Pallier
    model = Album
130 1 Etienne Pallier
    fields = ("name",)
131 1 Etienne Pallier
    show_change_link = True
132 1 Etienne Pallier
133 1 Etienne Pallier
134 1 Etienne Pallier
For StrategyObs.alerts, we will need :
135 1 Etienne Pallier
136 1 Etienne Pallier
class AlertInline(admin.TabularInline):
137 1 Etienne Pallier
    model = Alert
138 1 Etienne Pallier
    fields = ("request.name",) # there is no 'name' attribute in the Alert model
139 1 Etienne Pallier
    show_change_link = True
140 1 Etienne Pallier
141 1 Etienne Pallier
</pre>
142 1 Etienne Pallier
143 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 :
144 1 Etienne Pallier
145 1 Etienne Pallier
<pre>
146 1 Etienne Pallier
For Request.sequences :
147 1 Etienne Pallier
148 1 Etienne Pallier
class RequestAdmin(admin.ModelAdmin):
149 1 Etienne Pallier
    inlines = [
150 1 Etienne Pallier
	SequenceInline,
151 1 Etienne Pallier
    ]
152 1 Etienne Pallier
153 1 Etienne Pallier
For Detector.filters and Detector.albums :
154 1 Etienne Pallier
155 1 Etienne Pallier
class DetectorAdmin(admin.ModelAdmin):
156 1 Etienne Pallier
    inlines = [
157 1 Etienne Pallier
	FilterInline,
158 1 Etienne Pallier
        AlbumInline,
159 1 Etienne Pallier
    ]
160 1 Etienne Pallier
161 1 Etienne Pallier
</pre>
162 1 Etienne Pallier
163 1 Etienne Pallier
164 1 Etienne Pallier
* The many-to-many relationships are the following :
165 1 Etienne Pallier
166 1 Etienne Pallier
    * ScientificProgram - User
167 1 Etienne Pallier
    * ScheduleHistory - Sequence
168 1 Etienne Pallier
169 1 Etienne Pallier
* For each many-to-many relationship, declare a new "Inline" class in admin.py just after the imports, like this :
170 1 Etienne Pallier
171 1 Etienne Pallier
<pre>
172 1 Etienne Pallier
For ScientificProgram - User :
173 1 Etienne Pallier
174 1 Etienne Pallier
class UserAndSPInline(admin.TabularInline):
175 1 Etienne Pallier
    model = ScientificProgram.users.through
176 1 Etienne Pallier
177 1 Etienne Pallier
178 1 Etienne Pallier
For ScheduleHistory - Sequence
179 1 Etienne Pallier
180 1 Etienne Pallier
class SequenceAndSHInline(admin.TabularInline):
181 1 Etienne Pallier
    model = ScheduleHistory.sequences.through
182 1 Etienne Pallier
183 1 Etienne Pallier
</pre>
184 1 Etienne Pallier
185 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.
186 1 Etienne Pallier
187 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 :
188 1 Etienne Pallier
189 1 Etienne Pallier
<pre>
190 1 Etienne Pallier
For the ScheduleHistory - Sequence relationship :
191 1 Etienne Pallier
192 1 Etienne Pallier
class ScheduleHistoryAdmin(admin.ModelAdmin):
193 1 Etienne Pallier
    inlines = [
194 1 Etienne Pallier
        SequenceAndSHInline,
195 1 Etienne Pallier
    ]
196 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
197 1 Etienne Pallier
198 1 Etienne Pallier
class SequenceAdmin(admin.ModelAdmin):
199 1 Etienne Pallier
    inlines = [
200 1 Etienne Pallier
        AlbumInline,        # This is the Inline for the one-to-many relationship Sequence.albums
201 1 Etienne Pallier
        SequenceAndSHInline,                                                                
202 1 Etienne Pallier
    ]
203 1 Etienne Pallier
204 1 Etienne Pallier
For the ScientificProgram - User relationship :
205 1 Etienne Pallier
206 1 Etienne Pallier
class ScientificProgramAdmin(admin.ModelAdmin):
207 1 Etienne Pallier
    inlines = [
208 1 Etienne Pallier
        RequestInline,
209 1 Etienne Pallier
	UserAndSPInline,                                                                         
210 1 Etienne Pallier
    ]
211 1 Etienne Pallier
    exclude = ('users',) # Same as ScheduleHistory                                                                         
212 1 Etienne Pallier
213 1 Etienne Pallier
class UserAdmin(admin.ModelAdmin):
214 1 Etienne Pallier
    inlines = [
215 1 Etienne Pallier
	RequestInline,   # This is the Inline for the one-to-many relationship User.requests
216 1 Etienne Pallier
        UserAndSPInline,                                                                    
217 1 Etienne Pallier
    ]
218 1 Etienne Pallier
219 1 Etienne Pallier
</pre>
220 1 Etienne Pallier
221 1 Etienne Pallier
* For each ModelAdmin class in the admin.py, change the registering line
222 1 Etienne Pallier
223 1 Etienne Pallier
<pre>
224 1 Etienne Pallier
admin.site.register(Album)
225 1 Etienne Pallier
</pre>
226 1 Etienne Pallier
227 1 Etienne Pallier
to
228 1 Etienne Pallier
229 1 Etienne Pallier
<pre>
230 1 Etienne Pallier
admin.site.register(Album, AlbumAdmin)
231 1 Etienne Pallier
</pre>