vigiboard / vigiboard / controllers / vigiboardrequest.py @ c94dc931
History | View | Annotate | Download (15.7 KB)
1 | 19e88cb8 | Thomas ANDREJAK | # -*- coding: utf-8 -*-
|
---|---|---|---|
2 | 65383903 | Francois POIROTTE | # vim:set expandtab tabstop=4 shiftwidth=4:
|
3 | c94dc931 | Francois POIROTTE | # Copyright (C) 2007-2020 CS-SI
|
4 | 9b8d9497 | Francois POIROTTE | # License: GNU GPL v2 <http://www.gnu.org/licenses/gpl-2.0.html>
|
5 | a77de887 | Francois POIROTTE | |
6 | 19e88cb8 | Thomas ANDREJAK | """Gestion de la requête, des plugins et de l'affichage du Vigiboard"""
|
7 | |||
8 | 80fa03cd | Francois POIROTTE | import logging |
9 | 7365fb51 | Francois POIROTTE | from time import mktime |
10 | |||
11 | e181e86c | Francois POIROTTE | from tg import config, tmpl_context, request, url |
12 | 02c4a1e7 | Francois POIROTTE | from tg.i18n import ugettext as _ |
13 | 80fa03cd | Francois POIROTTE | from paste.deploy.converters import aslist |
14 | b2346a00 | Francois POIROTTE | |
15 | 6ab72614 | Vincent QUEMENER | from sqlalchemy import not_, and_, asc, desc |
16 | 8b2edebe | Aurelien BOMPARD | from sqlalchemy.sql.expression import null as expr_null, union_all |
17 | cf3c2494 | Vincent QUEMENER | from sqlalchemy.orm import contains_eager |
18 | 7365fb51 | Francois POIROTTE | |
19 | e7e3d45e | Francois POIROTTE | from vigilo.models.session import DBSession |
20 | from vigilo.models.tables import Event, CorrEvent, EventHistory, \ |
||
21 | 916e4b79 | Francois POIROTTE | Host, LowLevelService, StateName, UserSupItem |
22 | e181e86c | Francois POIROTTE | from vigiboard.widgets.edit_event import EditEventForm |
23 | 86662bc9 | Francois POIROTTE | from vigiboard.controllers.plugins import VigiboardRequestPlugin, INNER, ITEMS |
24 | 7365fb51 | Francois POIROTTE | |
25 | 80fa03cd | Francois POIROTTE | LOGGER = logging.getLogger(__name__) |
26 | |||
27 | 19e88cb8 | Thomas ANDREJAK | class VigiboardRequest(): |
28 | 86c3ae23 | Francois POIROTTE | """
|
29 | Classe gérant la génération de la requête finale,
|
||
30 | le préformatage des événements et celui des historiques
|
||
31 | """
|
||
32 | |||
33 | 5a845c93 | Vincent QUEMENER | def __init__(self, user, mask_closed_events=True, search=None, sort=None, order=None): |
34 | 19e88cb8 | Thomas ANDREJAK | """
|
35 | 54644278 | Francois POIROTTE | Initialisation de l'objet qui effectue les requêtes de VigiBoard
|
36 | sur la base de données.
|
||
37 | Cet objet est responsable de la vérification des droits de
|
||
38 | l'utilisateur sur les données manipulées.
|
||
39 | 5a845c93 | Vincent QUEMENER |
|
40 | @param user: Nom de l'utilisateur cherchant à afficher les événements.
|
||
41 | @type user: C{str}
|
||
42 | @param mask_closed_events: Booléen indiquant si l'on souhaite masquer les
|
||
43 | événements fermés ou non.
|
||
44 | @type mask_closed_events: C{boolean}
|
||
45 | @param search: Dictionnaire contenant les critères de recherche.
|
||
46 | @type search: C{dict}
|
||
47 | @param sort: Colonne de tri; vide en l'absence de tri.
|
||
48 | @type sort: C{unicode}
|
||
49 | @param order: Ordre du tri ("asc" ou "desc"); vide en l'absence de tri.
|
||
50 | @type order: C{unicode}
|
||
51 |
|
||
52 | 19e88cb8 | Thomas ANDREJAK | """
|
53 | |||
54 | 0f0e32ed | Francois POIROTTE | # Permet s'appliquer des filtres de recherche aux sous-requêtes.
|
55 | self.subqueries = []
|
||
56 | 19e88cb8 | Thomas ANDREJAK | self.generaterq = False |
57 | 24d74687 | Francois POIROTTE | |
58 | 86662bc9 | Francois POIROTTE | # Éléments à retourner (SELECT ...)
|
59 | self.table = []
|
||
60 | |||
61 | # Tables sur lesquelles porte la récupération (JOIN)
|
||
62 | self.join = []
|
||
63 | |||
64 | # Options à ajouter la requête
|
||
65 | self.option = []
|
||
66 | |||
67 | # Tables sur lesquelles porte la récupération (OUTER JOIN)
|
||
68 | self.outerjoin = []
|
||
69 | |||
70 | # Critères de filtrage (WHERE)
|
||
71 | self.filter = []
|
||
72 | |||
73 | # Regroupements (GROUP BY)
|
||
74 | # PostgreSQL est pointilleux sur les colonnes qui apparaissent
|
||
75 | # dans la clause GROUP BY. Si une colonne apparaît dans ORDER BY,
|
||
76 | # elle doit systématiquement apparaître AUSSI dans GROUP BY.
|
||
77 | self.groupby = [
|
||
78 | StateName.order, |
||
79 | Event.timestamp, |
||
80 | 8ba2de75 | Francois POIROTTE | CorrEvent.ack, |
81 | 86662bc9 | Francois POIROTTE | CorrEvent.priority, |
82 | StateName.statename, |
||
83 | ] |
||
84 | |||
85 | self.req = DBSession
|
||
86 | self.plugin = []
|
||
87 | self.events = []
|
||
88 | |||
89 | 73119f8a | Francois POIROTTE | # Si l'utilisateur est privilégié, il a accès
|
90 | # à tous les hôtes/services sans restriction.
|
||
91 | if config.is_manager.is_met(request.environ):
|
||
92 | 180b869a | Vincent QUEMENER | # Sélection de tous les services de la BDD.
|
93 | 0f0e32ed | Francois POIROTTE | lls_query = DBSession.query( |
94 | 180b869a | Vincent QUEMENER | LowLevelService.idservice.label("idsupitem"),
|
95 | LowLevelService.servicename.label("servicename"),
|
||
96 | Host.name.label("hostname"),
|
||
97 | b2668166 | Francois POIROTTE | Host.address.label("address"),
|
98 | 180b869a | Vincent QUEMENER | ).join( |
99 | (Host, Host.idhost == LowLevelService.idhost), |
||
100 | 0f0e32ed | Francois POIROTTE | ).distinct() |
101 | 180b869a | Vincent QUEMENER | |
102 | # Sélection de tous les hôtes de la BDD.
|
||
103 | 0f0e32ed | Francois POIROTTE | host_query = DBSession.query( |
104 | 180b869a | Vincent QUEMENER | Host.idhost.label("idsupitem"),
|
105 | expr_null().label("servicename"),
|
||
106 | Host.name.label("hostname"),
|
||
107 | b2668166 | Francois POIROTTE | Host.address.label("address"),
|
108 | 032d0f30 | Vincent QUEMENER | ).distinct() |
109 | 0f0e32ed | Francois POIROTTE | |
110 | # Application des filtres des plugins si nécessaire.
|
||
111 | if search is not None: |
||
112 | # On tire ici partie du fait que les listes sont passées
|
||
113 | # par référence dans les fonctions.
|
||
114 | subqueries = [lls_query, host_query] |
||
115 | 8b2edebe | Aurelien BOMPARD | for _plugin, instance in config.get('columns_plugins', []): |
116 | 86662bc9 | Francois POIROTTE | instance.handle_search_fields( |
117 | self, search, INNER, subqueries)
|
||
118 | 0f0e32ed | Francois POIROTTE | lls_query = subqueries[0]
|
119 | host_query = subqueries[1]
|
||
120 | 180b869a | Vincent QUEMENER | |
121 | # Union des deux sélections précédentes
|
||
122 | self.items = union_all(
|
||
123 | 0f0e32ed | Francois POIROTTE | lls_query, |
124 | host_query, |
||
125 | 180b869a | Vincent QUEMENER | correlate=False
|
126 | ).alias() |
||
127 | |||
128 | # Sinon, on ne récupère que les hôtes/services auquel il a accès.
|
||
129 | else:
|
||
130 | 916e4b79 | Francois POIROTTE | items = DBSession.query( |
131 | 180b869a | Vincent QUEMENER | UserSupItem.idsupitem, |
132 | UserSupItem.servicename, |
||
133 | UserSupItem.hostname, |
||
134 | b2668166 | Francois POIROTTE | UserSupItem.address, |
135 | 180b869a | Vincent QUEMENER | ).filter( |
136 | UserSupItem.username == user.user_name |
||
137 | 0f0e32ed | Francois POIROTTE | ).distinct() |
138 | 180b869a | Vincent QUEMENER | |
139 | 0f0e32ed | Francois POIROTTE | # Application des filtres des plugins si nécessaire.
|
140 | if search is not None: |
||
141 | # On tire ici partie du fait que les listes sont passées
|
||
142 | # par référence dans les fonctions.
|
||
143 | subqueries = [items] |
||
144 | 8b2edebe | Aurelien BOMPARD | for _plugin, instance in config.get('columns_plugins', []): |
145 | 86662bc9 | Francois POIROTTE | instance.handle_search_fields( |
146 | self, search, INNER, subqueries)
|
||
147 | 0f0e32ed | Francois POIROTTE | items = subqueries[0]
|
148 | 916e4b79 | Francois POIROTTE | |
149 | 86662bc9 | Francois POIROTTE | # Permet d'avoir le même format que pour l'autre requête.
|
150 | 0f0e32ed | Francois POIROTTE | self.items = items.subquery()
|
151 | 8484b8bd | Francois POIROTTE | |
152 | 5a845c93 | Vincent QUEMENER | # Tris (ORDER BY)
|
153 | # Permet de répondre aux exigences suivantes :
|
||
154 | # - VIGILO_EXIG_VIGILO_BAC_0050
|
||
155 | # - VIGILO_EXIG_VIGILO_BAC_0060
|
||
156 | self.orderby = []
|
||
157 | 80fa03cd | Francois POIROTTE | plugins = config.get('columns_plugins', [])
|
158 | 5a845c93 | Vincent QUEMENER | if sort:
|
159 | 80fa03cd | Francois POIROTTE | for _plugin, instance in plugins: |
160 | 5a845c93 | Vincent QUEMENER | criterion = instance.get_sort_criterion(self, sort)
|
161 | if criterion is not None: |
||
162 | if order == 'asc': |
||
163 | self.orderby.append(asc(criterion))
|
||
164 | else:
|
||
165 | self.orderby.append(desc(criterion))
|
||
166 | |||
167 | 80fa03cd | Francois POIROTTE | default_sort = aslist(config.get('default_sort', '')) |
168 | for sort_column in default_sort: |
||
169 | criterion = None
|
||
170 | sort_field, _dummy, sort_order = sort_column.partition(':')
|
||
171 | for _plugin, instance in plugins: |
||
172 | criterion = instance.get_sort_criterion(self, sort_field)
|
||
173 | if criterion is not None: |
||
174 | if sort_order == 'desc': |
||
175 | self.orderby.append(desc(criterion))
|
||
176 | elif sort_order in ('asc', None): |
||
177 | self.orderby.append(asc(criterion))
|
||
178 | else:
|
||
179 | self.orderby.append(asc(criterion))
|
||
180 | LOGGER.warn('Invalid sort order: "%s", sorting in '
|
||
181 | 'ascending order instead', sort_order)
|
||
182 | break
|
||
183 | if criterion is None: |
||
184 | LOGGER.info('No such plugin: "%s"', sort_field)
|
||
185 | 5a845c93 | Vincent QUEMENER | |
186 | 86662bc9 | Francois POIROTTE | if search is not None: |
187 | # 2nde passe pour les filtres : self.items est désormais défini.
|
||
188 | 80fa03cd | Francois POIROTTE | for _plugin, instance in plugins: |
189 | 86662bc9 | Francois POIROTTE | instance.handle_search_fields(self, search, ITEMS, subqueries)
|
190 | 911069bc | Francois POIROTTE | |
191 | 54644278 | Francois POIROTTE | if mask_closed_events:
|
192 | self.filter.append(
|
||
193 | # On masque les événements avec l'état OK
|
||
194 | 8ba2de75 | Francois POIROTTE | # et traités (ack == CorrEvent.ACK_CLOSED).
|
195 | 54644278 | Francois POIROTTE | not_(and_( |
196 | StateName.statename.in_([u'OK', u'UP']), |
||
197 | 8ba2de75 | Francois POIROTTE | CorrEvent.ack == CorrEvent.ACK_CLOSED |
198 | 54644278 | Francois POIROTTE | )) |
199 | ) |
||
200 | 8484b8bd | Francois POIROTTE | |
201 | 19e88cb8 | Thomas ANDREJAK | |
202 | def add_plugin(self, *argv): |
||
203 | """
|
||
204 | Ajout d'un plugin, on lui prélève ses ajouts dans la requête
|
||
205 | """
|
||
206 | df66bc2c | Francois POIROTTE | for i in argv: |
207 | 19e88cb8 | Thomas ANDREJAK | if isinstance(i, VigiboardRequestPlugin): |
208 | df66bc2c | Francois POIROTTE | if i.table:
|
209 | 19e88cb8 | Thomas ANDREJAK | self.add_table(*i.table)
|
210 | df66bc2c | Francois POIROTTE | if i.join:
|
211 | 19e88cb8 | Thomas ANDREJAK | self.add_join(*i.join)
|
212 | df66bc2c | Francois POIROTTE | if i.outerjoin:
|
213 | 19e88cb8 | Thomas ANDREJAK | self.add_outer_join(*i.outerjoin)
|
214 | df66bc2c | Francois POIROTTE | if i.filter:
|
215 | 19e88cb8 | Thomas ANDREJAK | self.add_filter(*i.filter)
|
216 | 65383903 | Francois POIROTTE | if i.groupby:
|
217 | 19e88cb8 | Thomas ANDREJAK | self.add_group_by(*i.groupby)
|
218 | df66bc2c | Francois POIROTTE | if i.orderby:
|
219 | 19e88cb8 | Thomas ANDREJAK | self.add_order_by(*i.orderby)
|
220 | self.plugin.append(i)
|
||
221 | |||
222 | def generate_request(self): |
||
223 | """
|
||
224 | Génération de la requête avec l'ensemble des données stockées
|
||
225 | et la place dans la variable rq de la classe
|
||
226 | """
|
||
227 | 911069bc | Francois POIROTTE | if self.generaterq: |
228 | return
|
||
229 | |||
230 | 65383903 | Francois POIROTTE | for plugin in config['columns_plugins']: |
231 | self.add_plugin(plugin)
|
||
232 | bc94248f | Francois POIROTTE | |
233 | b00c0ea7 | Francois POIROTTE | # Toutes les requêtes ont besoin de récupérer l'état courant
|
234 | # de l'événement.
|
||
235 | 5d20c2c5 | Francois POIROTTE | self.join.append((StateName, StateName.idstatename == \
|
236 | Event.current_state)) |
||
237 | b00c0ea7 | Francois POIROTTE | |
238 | # PostgreSQL est pointilleux sur les colonnes qui apparaissent
|
||
239 | # dans la clause GROUP BY. Si une colonne apparaît dans SELECT,
|
||
240 | # elle doit systématiquement apparaître AUSSI dans GROUP BY.
|
||
241 | # Ici, on ajoute automatiquement les colonnes du SELECT au GROUP BY.
|
||
242 | 911069bc | Francois POIROTTE | self.add_group_by(*self.table) |
243 | |||
244 | 19e88cb8 | Thomas ANDREJAK | # query et join ont besoin de referrence
|
245 | self.req = self.req.query(*self.table) |
||
246 | self.req = self.req.join(*self.join) |
||
247 | cf3c2494 | Vincent QUEMENER | self.req = self.req.options(*self.option) |
248 | 19e88cb8 | Thomas ANDREJAK | |
249 | # le reste, non
|
||
250 | for i in self.outerjoin: |
||
251 | self.req = self.req.outerjoin(i) |
||
252 | for i in self.filter: |
||
253 | self.req = self.req.filter(i) |
||
254 | for i in self.groupby: |
||
255 | self.req = self.req.group_by(i) |
||
256 | for i in self.orderby: |
||
257 | self.req = self.req.order_by(i) |
||
258 | 911069bc | Francois POIROTTE | self.generaterq = True |
259 | |||
260 | 19e88cb8 | Thomas ANDREJAK | def num_rows(self): |
261 | """
|
||
262 | Retourne le nombre de lignes de la requête.
|
||
263 | Si celle-ci n'est pas encore générée, on le fait.
|
||
264 |
|
||
265 | 0bd9c069 | Francois POIROTTE | @return: Nombre de ligne
|
266 | 19e88cb8 | Thomas ANDREJAK | """
|
267 | |||
268 | 911069bc | Francois POIROTTE | self.generate_request()
|
269 | 19e88cb8 | Thomas ANDREJAK | return self.req.count() |
270 | |||
271 | def add_table(self, *argv): |
||
272 | """
|
||
273 | Ajoute une ou plusieurs tables/élément d'une table à
|
||
274 | la requête.
|
||
275 |
|
||
276 | @param argv: Liste des tables à ajouter
|
||
277 | """
|
||
278 | 65383903 | Francois POIROTTE | |
279 | 8484b8bd | Francois POIROTTE | # On vérifie qu'il n'y a pas de doublons dans la liste finale
|
280 | # des tables.
|
||
281 | 65383903 | Francois POIROTTE | |
282 | 19e88cb8 | Thomas ANDREJAK | for i in argv : |
283 | for j in self.table: |
||
284 | if str(i) == str(j): |
||
285 | break
|
||
286 | self.table.append(i)
|
||
287 | |||
288 | def add_join(self, *argv): |
||
289 | """
|
||
290 | Ajoute une ou plusieurs jointures à
|
||
291 | la requête.
|
||
292 |
|
||
293 | @param argv: Liste des jointures à ajouter
|
||
294 | """
|
||
295 | 65383903 | Francois POIROTTE | |
296 | 8484b8bd | Francois POIROTTE | # On vérifie qu'il n'y a pas de doublons dans la liste finale
|
297 | # des jointures.
|
||
298 | 65383903 | Francois POIROTTE | |
299 | 19e88cb8 | Thomas ANDREJAK | for i in argv: |
300 | for j in self.join: |
||
301 | if str(i) == str(j): |
||
302 | break
|
||
303 | self.join.append(i)
|
||
304 | |||
305 | cf3c2494 | Vincent QUEMENER | def add_option(self, *argv): |
306 | """
|
||
307 | Ajoute une ou plusieurs options à la requête.
|
||
308 |
|
||
309 | @param argv: Liste des options à ajouter
|
||
310 | """
|
||
311 | |||
312 | # On vérifie qu'il n'y a pas de doublons
|
||
313 | # dans la liste finale des options.
|
||
314 | |||
315 | for i in argv: |
||
316 | for j in self.option: |
||
317 | if str(i) == str(j): |
||
318 | break
|
||
319 | self.option.append(i)
|
||
320 | |||
321 | def add_contains_eager(self, relation): |
||
322 | """
|
||
323 | Ajoute une option de type contains_eager à la
|
||
324 | requête pour la relation passée en paramètre.
|
||
325 | """
|
||
326 | self.add_option(contains_eager(relation))
|
||
327 | |||
328 | 19e88cb8 | Thomas ANDREJAK | def add_outer_join(self, *argv): |
329 | """
|
||
330 | Ajoute une ou plusieurs jointures externes à
|
||
331 | la requête.
|
||
332 |
|
||
333 | @param argv: Liste des jointures externes à ajouter
|
||
334 | """
|
||
335 | 65383903 | Francois POIROTTE | |
336 | 8484b8bd | Francois POIROTTE | # On vérifie qu'il n'y a pas de doublons dans la liste finale
|
337 | # des jointures externes.
|
||
338 | 65383903 | Francois POIROTTE | |
339 | 19e88cb8 | Thomas ANDREJAK | for i in argv: |
340 | for j in self.outerjoin: |
||
341 | if str(i) == str(j): |
||
342 | break
|
||
343 | 65383903 | Francois POIROTTE | self.outerjoin.append(i)
|
344 | 19e88cb8 | Thomas ANDREJAK | |
345 | def add_filter(self, *argv): |
||
346 | """
|
||
347 | Ajoute un ou plusieurs filtres à la requête.
|
||
348 |
|
||
349 | @param argv: Liste des filtres à ajouter
|
||
350 | """
|
||
351 | 65383903 | Francois POIROTTE | |
352 | 8484b8bd | Francois POIROTTE | # On vérifie qu'il n'y a pas de doublons dans la liste finale
|
353 | # des filtres.
|
||
354 | 65383903 | Francois POIROTTE | |
355 | 19e88cb8 | Thomas ANDREJAK | for i in argv: |
356 | for j in self.filter: |
||
357 | if str(i) == str(j): |
||
358 | break
|
||
359 | self.filter.append(i)
|
||
360 | |||
361 | def add_group_by(self, *argv): |
||
362 | """
|
||
363 | Ajoute un ou plusieurs groupements à la requête.
|
||
364 |
|
||
365 | @param argv: Liste des groupements à ajouter
|
||
366 | """
|
||
367 | 65383903 | Francois POIROTTE | |
368 | 8484b8bd | Francois POIROTTE | # On vérifie qu'il n'y a pas de doublons dans la liste finale
|
369 | # des groupements.
|
||
370 | 65383903 | Francois POIROTTE | |
371 | 19e88cb8 | Thomas ANDREJAK | for i in argv: |
372 | for j in self.groupby: |
||
373 | df66bc2c | Francois POIROTTE | try:
|
374 | if str(i) == str(j): |
||
375 | break
|
||
376 | # SQLAlchemy lève cette exception pour certains attributes,
|
||
377 | # par exemple les attributs définis avec synonym().
|
||
378 | except AttributeError: |
||
379 | pass
|
||
380 | 19e88cb8 | Thomas ANDREJAK | self.groupby.append(i)
|
381 | |||
382 | def add_order_by(self, *argv): |
||
383 | """
|
||
384 | Ajoute un ou plusieurs orders à la requête.
|
||
385 |
|
||
386 | @param argv: Liste des ordres à ajouter
|
||
387 | """
|
||
388 | 65383903 | Francois POIROTTE | |
389 | 8484b8bd | Francois POIROTTE | # On vérifie qu'il n'y a pas de doublons dans la liste finale
|
390 | # des ordres.
|
||
391 | 65383903 | Francois POIROTTE | |
392 | 19e88cb8 | Thomas ANDREJAK | for i in argv: |
393 | for j in self.orderby: |
||
394 | if str(i) == str(j): |
||
395 | break
|
||
396 | self.orderby.append(i)
|
||
397 | |||
398 | def format_events(self, first_row, last_row): |
||
399 | """
|
||
400 | Formate la réponse de la requête et y applique les plugins
|
||
401 | pour un affichage simple du résultat par Genshi.
|
||
402 | On génère une liste de liste, chaqu'une étant la description de
|
||
403 | a2a22ade | Francois POIROTTE | l'affichage pour un événement donné.
|
404 | 19e88cb8 | Thomas ANDREJAK |
|
405 | a2a22ade | Francois POIROTTE | @param first_row: Indice de début de la liste des événements
|
406 | @param last_row: Indice de fin de la liste des événements
|
||
407 | 19e88cb8 | Thomas ANDREJAK | """
|
408 | 65383903 | Francois POIROTTE | |
409 | 19e88cb8 | Thomas ANDREJAK | # Si la requête n'est pas générée, on le fait
|
410 | 911069bc | Francois POIROTTE | self.generate_request()
|
411 | 19e88cb8 | Thomas ANDREJAK | |
412 | # Liste des éléments pour la tête du tableau
|
||
413 | 15b98053 | Francois POIROTTE | self.events = []
|
414 | 19e88cb8 | Thomas ANDREJAK | |
415 | 15b98053 | Francois POIROTTE | for data in self.req[first_row : last_row]: |
416 | 94f31908 | Francois POIROTTE | self.events.append(data)
|
417 | 19e88cb8 | Thomas ANDREJAK | |
418 | 8484b8bd | Francois POIROTTE | def format_history(self): |
419 | 19e88cb8 | Thomas ANDREJAK | """
|
420 | a2a22ade | Francois POIROTTE | Formate les historiques correspondant aux événements sélectionnés
|
421 | 19e88cb8 | Thomas ANDREJAK | pour un affichage simple du résultat par Genshi.
|
422 | 8484b8bd | Francois POIROTTE | On génère une liste de liste, chaqu'une étant la description
|
423 | de l'affichage pour un historique donné.
|
||
424 | 19e88cb8 | Thomas ANDREJAK | """
|
425 | |||
426 | 539f69fc | Francois POIROTTE | ids = [data[0].idevent for data in self.events] |
427 | ee3ae8c8 | Francois POIROTTE | history = DBSession.query( |
428 | EventHistory, |
||
429 | 15b98053 | Francois POIROTTE | ).filter(EventHistory.idevent.in_(ids) |
430 | 19e88cb8 | Thomas ANDREJAK | ).order_by(desc(EventHistory.timestamp) |
431 | ).order_by(desc(EventHistory.idhistory)) |
||
432 | 539f69fc | Francois POIROTTE | return history
|
433 | 19e88cb8 | Thomas ANDREJAK | |
434 | 24d4f8b0 | Vincent QUEMENER | def generate_tmpl_context(self): |
435 | 19e88cb8 | Thomas ANDREJAK | """
|
436 | b2668166 | Francois POIROTTE | Génère et peuple la variable tmpl_context avec les dialogues et
|
437 | 19e88cb8 | Thomas ANDREJAK | formulaires nécessaire au fonctionnement de Vigiboard
|
438 | """
|
||
439 | |||
440 | 97f6d842 | Vincent QUEMENER | from vigiboard.controllers.root import get_last_modification_timestamp |
441 | bcf87133 | Francois POIROTTE | |
442 | # Si les objets manipulés sont des Event, on a facilement les idevent.
|
||
443 | 94f31908 | Francois POIROTTE | if not len(self.events): |
444 | ids = [] |
||
445 | elif isinstance(self.events[0][0], Event): |
||
446 | bcf87133 | Francois POIROTTE | ids = [data[0].idevent for data in self.events] |
447 | # Sinon, il s'agit de CorrEvent(s) dont on récupère l'idcause.
|
||
448 | else:
|
||
449 | ids = [data[0].idcause for data in self.events] |
||
450 | e9ccb711 | Francois POIROTTE | |
451 | 57387640 | Francois POIROTTE | # Ajout des formulaires et préparation
|
452 | # des données pour ces formulaires.
|
||
453 | tmpl_context.last_modification = \ |
||
454 | mktime(get_last_modification_timestamp(ids).timetuple()) |
||
455 | |||
456 | e181e86c | Francois POIROTTE | tmpl_context.edit_event_form = EditEventForm("edit_event_form",
|
457 | a5f99051 | Francois POIROTTE | submit_text=_('Apply'), action=url('/update')) |