Django backoffice config

Version 2 (Etienne Pallier, 03/23/2016 08:30 am)

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