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> |