[#2645] Ajouté le champ sigle à ref_etablissement
[auf_django_references.git] / auf / django / references / models.py
1 # -=- encoding: utf-8 -=-
2
3 from django.conf import settings
4 from django.db import models
5
6 MANAGED = getattr(settings, 'AUF_REFERENCES_MANAGED', False)
7
8
9 ### Gestion des actifs/inactifs
10
11 class ActifsManager(models.Manager):
12 """
13 Manager pour ``ActifsModel``.
14 """
15
16 def get_query_set(self):
17 return super(ActifsManager, self).get_query_set().filter(actif=True)
18
19
20 class ActifsModel(models.Model):
21 """
22 Modèle faisant la gestion des objets actifs/inactifs.
23
24 Le manager par défaut ne liste que les objets actifs. Pour avoir tous
25 les objets, utiliser le manager ``avec_inactifs``.
26 """
27 actif = models.BooleanField(default=True, editable=False)
28
29 # Managers
30 objects = ActifsManager()
31 avec_inactifs = models.Manager()
32
33 class Meta:
34 abstract = True
35
36
37 ### Modèles pour les données de référence
38
39 class Employe(ActifsModel):
40 """
41 Personne en contrat d'employé (CDD ou CDI) à l'AUF
42 """
43 nom = models.CharField(max_length=255)
44 prenom = models.CharField(max_length=255)
45 implantation = models.ForeignKey(
46 'references.Implantation',
47 db_column='implantation',
48 related_name='lieu_travail_theorique_de'
49 )
50 implantation_physique = models.ForeignKey(
51 'references.Implantation',
52 db_column='implantation_physique',
53 related_name='lieu_travail_reel_de'
54 )
55 courriel = models.CharField(max_length=255, null=True, blank=True)
56 genre = models.CharField(max_length=3)
57 fonction = models.CharField(max_length=255, null=True, blank=True)
58 telephone_poste = models.CharField(max_length=255, null=True, blank=True)
59 telephone_ip = models.CharField(max_length=255, null=True, blank=True)
60 responsable = models.ForeignKey(
61 'references.Employe',
62 db_column='responsable',
63 related_name='responsable_de',
64 null=True, blank=True
65 )
66 mandat_debut = models.DateField(null=True, blank=True)
67 mandat_fin = models.DateField(null=True, blank=True)
68 date_entree = models.DateField(null=True, blank=True)
69 service = models.ForeignKey('references.Service', db_column='service')
70 poste_type_1 = models.ForeignKey(
71 'references.PosteType',
72 null=True, blank=True,
73 db_column='poste_type_1',
74 related_name='poste_type_1'
75 )
76 poste_type_2 = models.ForeignKey(
77 'references.PosteType',
78 null=True, blank=True,
79 db_column='poste_type_2',
80 related_name='poste_type_2'
81 )
82
83 class Meta:
84 db_table = u'ref_employe'
85 ordering = ['nom']
86 managed = MANAGED
87
88 def __unicode__(self):
89 return u"%s, %s [%d]" % (self.nom, self.prenom, self.id)
90
91
92 class Authentification(ActifsModel):
93 """Authentification"""
94 id = models.ForeignKey(
95 'references.Employe', primary_key=True, db_column='id'
96 )
97 courriel = models.CharField(max_length=255, unique=True)
98 motdepasse = models.CharField(max_length=255)
99
100 class Meta:
101 db_table = u'ref_authentification'
102 ordering = ['id']
103 managed = MANAGED
104
105 def __unicode__(self):
106 return u"%s [%d]" % (self.courriel, self.id)
107
108
109 class Service(ActifsModel):
110 """Services (donnée de référence, source: SGRH).
111 """
112 nom = models.CharField(max_length=255)
113
114 class Meta:
115 db_table = u'ref_service'
116 ordering = ['nom']
117 managed = MANAGED
118
119 def __unicode__(self):
120 return "%s (%s)" % (self.nom, self.id)
121
122
123 class PosteType(ActifsModel):
124 """Postes types (donnée de référence, source: SGRH).
125 """
126 nom = models.CharField(max_length=255)
127
128 class Meta:
129 db_table = u'ref_poste_type'
130 managed = MANAGED
131
132 def __unicode__(self):
133 return "%s (%s)" % (self.nom, self.id)
134
135
136 class GroupeArh(ActifsModel):
137 employe = models.ForeignKey('references.Employe', db_column='employe')
138
139 class Meta:
140 db_table = u'ref_groupe_arh'
141 managed = MANAGED
142
143
144 class GroupeDirRegion(ActifsModel):
145 employe = models.ForeignKey('references.Employe', db_column='employe')
146 region = models.ForeignKey('references.Region', db_column='region')
147
148 class Meta:
149 db_table = u'ref_groupe_dir_region'
150 managed = MANAGED
151
152
153 class GroupeAdmRegion(ActifsModel):
154 employe = models.ForeignKey('references.Employe', db_column='employe')
155 region = models.ForeignKey('references.Region', db_column='region')
156
157 class Meta:
158 db_table = u'ref_groupe_adm_region'
159 managed = MANAGED
160
161
162 class GroupeRespImplantation(ActifsModel):
163 employe = models.ForeignKey('references.Employe', db_column='employe')
164 implantation = models.ForeignKey(
165 'references.Implantation', db_column='implantation'
166 )
167 type = models.CharField(max_length=255, blank=True, null=True)
168
169 class Meta:
170 db_table = u'ref_groupe_resp_implantation'
171 managed = MANAGED
172
173
174 class GroupeDirProgramme(ActifsModel):
175 employe = models.ForeignKey('references.Employe', db_column='employe')
176 service = models.ForeignKey('references.Service', db_column='service')
177
178 class Meta:
179 db_table = u'ref_groupe_dir_programme'
180 managed = MANAGED
181
182
183 class GroupeDirDelegProgrammeReg(ActifsModel):
184 employe = models.ForeignKey('references.Employe', db_column='employe')
185 region = models.ForeignKey('references.Region', db_column='region')
186
187 class Meta:
188 db_table = u'ref_groupe_dir_deleg_programme_reg'
189 managed = MANAGED
190
191
192 class GroupeComptable(ActifsModel):
193 employe = models.ForeignKey('references.Employe', db_column='employe')
194
195 class Meta:
196 db_table = u'ref_groupe_comptable'
197 managed = MANAGED
198
199
200 class GroupeComptableRegional(ActifsModel):
201 employe = models.ForeignKey('references.Employe', db_column='employe')
202
203 class Meta:
204 db_table = u'ref_groupe_comptable_regional'
205 managed = MANAGED
206
207
208 class GroupeComptableLocal(ActifsModel):
209 employe = models.ForeignKey('references.Employe', db_column='employe')
210
211 class Meta:
212 db_table = u'ref_groupe_comptable_local'
213 managed = MANAGED
214
215
216 class Discipline(ActifsModel):
217 """ ATTENTION: DÉSUET
218 Discipline (donnée de référence, source: SQI).
219 Une discipline est une catégorie de savoirs scientifiques.
220 Le conseil scientifique fixe la liste des disciplines.
221 """
222 code = models.CharField(max_length=255, unique=True)
223 nom = models.CharField(max_length=255)
224 nom_long = models.CharField(max_length=255, blank=True)
225 nom_court = models.CharField(max_length=255, blank=True)
226
227 class Meta:
228 db_table = u'ref_discipline'
229 ordering = ['nom']
230 managed = MANAGED
231
232 def __unicode__(self):
233 return "%s - %s" % (self.code, self.nom)
234
235
236 class Programme(ActifsModel):
237 """ ATTENTION: DÉSUET
238 Programme (donnée de référence, source: SQI).
239 Structure interne par laquelle l'AUF exécute ses projets et activités,
240 dispense ses produits et ses services.
241 """
242 code = models.CharField(max_length=255, unique=True)
243 nom = models.CharField(max_length=255)
244 nom_long = models.CharField(max_length=255, blank=True)
245 nom_court = models.CharField(max_length=255, blank=True)
246
247 class Meta:
248 db_table = u'ref_programme'
249 managed = MANAGED
250
251 def __unicode__(self):
252 return "%s - %s" % (self.code, self.nom)
253
254
255 #PROGRAMMATION QUADRIENNALLE
256
257 class Projet(ActifsModel):
258 """Projet (donnée de référence, source: programmation-quadriennalle).
259 """
260 SERVICE_CHOICES = (
261 ('1',
262 "Direction de la langue et de la communication scientifique "
263 "en français"),
264 ('2', "Direction du développement et de la valorisation"),
265 ('3',
266 "Direction de l'innovation pédagogique et de l'économie "
267 "de la connaissance"),
268 ('4', "Direction du renforcement des capacités scientifiques"),
269 )
270 code = models.CharField(max_length=255, unique=True)
271 nom = models.CharField(max_length=255)
272 presentation = models.TextField(null=True, blank=True)
273 partenaires = models.TextField(null=True, blank=True)
274 service = models.CharField(
275 max_length=255, choices=SERVICE_CHOICES, blank=True, null=True
276 )
277 objectif_specifique = models.ForeignKey(
278 'references.ObjectifSpecifique',
279 blank=True, null=True,
280 db_column='objectif_specifique'
281 )
282 implantation = models.ForeignKey('references.Implantation', null=True,
283 blank=True, db_column='implantation')
284 etablissement = models.ForeignKey('references.Etablissement', null=True,
285 blank=True, db_column='etablissement')
286 date_debut = models.DateField(null=True, blank=True)
287 date_fin = models.DateField(null=True, blank=True)
288
289 class Meta:
290 db_table = u'ref_projet'
291 ordering = ['nom']
292 managed = MANAGED
293
294 def __unicode__(self):
295 return "%s - %s" % (self.code, self.nom)
296
297
298 class ProjetComposante(ActifsModel):
299 """Composantes des projets (source: programmation-quadriennalle)
300 """
301 code = models.CharField(max_length=10)
302 nom = models.CharField(max_length=255)
303 nom_court = models.CharField(max_length=255, null=True, blank=True)
304 description = models.TextField(null=True, blank=True)
305 projet = models.ForeignKey('references.Projet', db_column='projet')
306
307 class Meta:
308 db_table = u'ref_projet_composante'
309 ordering = ['nom']
310 managed = MANAGED
311
312 def __unicode__(self):
313 return "%s - %s" % (self.code, self.nom)
314
315
316 class UniteProjet(ActifsModel):
317 """Unités de projet (source: programmation-quadriennalle)
318 """
319 code = models.CharField(max_length=10, unique=True)
320 nom = models.CharField(max_length=255)
321
322 class Meta:
323 db_table = u'ref_unite_projet'
324 ordering = ['nom']
325 managed = MANAGED
326
327 def __unicode__(self):
328 return "%s - %s" % (self.code, self.nom)
329
330
331 class ObjectifSpecifique(ActifsModel):
332 nom = models.CharField(max_length=255)
333 objectif_strategique = models.ForeignKey('references.ObjectifStrategique',
334 db_column='objectif_strategique')
335
336 class Meta:
337 db_table = u'ref_objectif_specifique'
338 ordering = ['nom']
339 managed = MANAGED
340
341 def __unicode__(self):
342 return "%s - %s" % (self.id, self.nom)
343
344
345 class ObjectifStrategique(ActifsModel):
346 nom = models.CharField(max_length=255)
347 description = models.TextField(null=True, blank=True)
348
349 class Meta:
350 db_table = u'ref_objectif_strategique'
351 ordering = ['nom']
352 managed = MANAGED
353
354 def __unicode__(self):
355 return "%s - %s" % (self.id, self.nom)
356
357
358 class Thematique(ActifsModel):
359 nom = models.CharField(max_length=255)
360
361 class Meta:
362 db_table = u'ref_thematique'
363 ordering = ['nom']
364 managed = MANAGED
365
366 def __unicode__(self):
367 return "%s - %s" % (self.id, self.nom)
368
369
370 class ProjetUp(ActifsModel):
371 """Projet-unité de projet (source: coda)
372 => codes budgétaires
373 """
374 code = models.CharField(max_length=255, unique=True)
375 nom = models.CharField(max_length=255)
376 nom_court = models.CharField(max_length=255, blank=True)
377
378 class Meta:
379 managed = MANAGED
380
381
382 class Poste(ActifsModel):
383 """ ATTENTION: DÉSUET
384 Poste (donnée de référence, source: CODA).
385 Un poste est une catégorie destinée à venir raffiner un projet.
386 """
387 code = models.CharField(max_length=255, unique=True)
388 nom = models.CharField(max_length=255)
389 type = models.CharField(max_length=255, blank=True)
390
391 class Meta:
392 db_table = u'ref_poste'
393 managed = MANAGED
394
395 def __unicode__(self):
396 return "%s - %s (%s)" % (self.code, self.nom, self.type)
397
398
399 class ProjetPoste(ActifsModel):
400 """
401 ATTENTION: DÉSUET
402 Projet-poste (donnée de référence, source: CODA).
403 Un projet-poste consiste en une raffinement d'un projet par un poste
404 (budgétaire). Subdivision utile pour le suivi budgétaire et comptable.
405 """
406 code = models.CharField(max_length=255, unique=True)
407 code_projet = models.ForeignKey(
408 'references.Projet', to_field='code', db_column='code_projet'
409 )
410 code_poste = models.ForeignKey(
411 'references.Poste', to_field='code', db_column='code_poste'
412 )
413 code_bureau = models.ForeignKey(
414 'references.Bureau', to_field='code', db_column='code_bureau'
415 )
416 code_programme = models.ForeignKey(
417 'references.Programme', to_field='code', db_column='code_programme'
418 )
419
420 class Meta:
421 db_table = u'ref_projet_poste'
422 managed = MANAGED
423
424 def __unicode__(self):
425 return "%s" % (self.code)
426
427
428 class Region(ActifsModel):
429 """Région (donnée de référence, source: referentiels_spip).
430 Une région est une subdivision géographique du monde pour la gestion de
431 l'AUF.
432 """
433 code = models.CharField(max_length=255, unique=True)
434 nom = models.CharField(max_length=255, db_index=True)
435 implantation_bureau = models.ForeignKey(
436 'references.Implantation', db_column='implantation_bureau',
437 related_name='gere_region', null=True, blank=True
438 )
439
440 class Meta:
441 db_table = u'ref_region'
442 ordering = ['nom']
443 verbose_name = u"région"
444 verbose_name_plural = u"régions"
445 managed = MANAGED
446
447 def __unicode__(self):
448 return "%s (%s)" % (self.nom, self.code)
449
450
451 class Bureau(ActifsModel):
452 """
453 Bureau (donnée de référence, source: SQI).
454
455 Référence legacy entre la notion de région et celle d'implantation
456 responsable des régions et du central.
457
458 Un bureau est :
459 - soit le bureau régional d'une région (implantations de type 'Bureau')
460 - soit la notion unique de Service central pour les 2 implantations
461 centrales (implantations de type 'Service central' et 'Siege').
462
463 Ne pas confondre avec les seuls 'bureaux régionaux'.
464 """
465 code = models.CharField(max_length=255, unique=True)
466 nom = models.CharField(max_length=255)
467 nom_court = models.CharField(max_length=255, blank=True)
468 nom_long = models.CharField(max_length=255, blank=True)
469 implantation = models.ForeignKey(
470 'references.Implantation', db_column='implantation'
471 )
472 region = models.ForeignKey('references.Region', db_column='region')
473
474 class Meta:
475 db_table = u'ref_bureau'
476 ordering = ['nom']
477 verbose_name = u"bureau"
478 verbose_name_plural = u"bureaux"
479 managed = MANAGED
480
481 def __unicode__(self):
482 return "%s (%s)" % (self.nom, self.code)
483
484
485 class Implantation(ActifsModel):
486 """
487 Implantation (donnée de référence, source: Implantus)
488
489 Une implantation est un endroit où l'AUF est présente et offre des
490 services spécifiques. Deux implantations peuvent être au même endroit
491 physique.
492 """
493 STATUT_CHOICES = (
494 (0, u'Fermée ou jamais ouverte'),
495 (1, u'Ouverte'),
496 (2, u'Ouverture imminente'),
497 (3, u'En projet')
498 )
499
500 nom = models.CharField(max_length=255)
501 nom_court = models.CharField(max_length=255, blank=True)
502 nom_long = models.CharField(max_length=255, blank=True)
503 type = models.CharField(max_length=255)
504 bureau_rattachement = models.ForeignKey(
505 'references.Implantation', db_column='bureau_rattachement'
506 )
507 region = models.ForeignKey('references.Region', db_column='region')
508 fuseau_horaire = models.CharField(max_length=255, blank=True)
509 code_meteo = models.CharField(max_length=255, blank=True)
510 # responsable
511 responsable_implantation = models.IntegerField(null=True, blank=True)
512 # adresse postale
513 adresse_postale_precision_avant = models.CharField(
514 max_length=255, blank=True, null=True
515 )
516 adresse_postale_no = models.CharField(max_length=30, blank=True, null=True)
517 adresse_postale_rue = models.CharField(
518 max_length=255, blank=True, null=True
519 )
520 adresse_postale_bureau = models.CharField(
521 max_length=255, blank=True, null=True
522 )
523 adresse_postale_precision = models.CharField(
524 max_length=255, blank=True, null=True
525 )
526 adresse_postale_boite_postale = models.CharField(
527 max_length=255, blank=True, null=True
528 )
529 adresse_postale_ville = models.CharField(max_length=255)
530 adresse_postale_code_postal = models.CharField(
531 max_length=20, blank=True, null=True
532 )
533 adresse_postale_code_postal_avant_ville = models.NullBooleanField()
534 adresse_postale_region = models.CharField(
535 max_length=255, blank=True, null=True
536 )
537 adresse_postale_pays = models.ForeignKey(
538 'references.Pays', to_field='code',
539 db_column='adresse_postale_pays',
540 related_name='impl_adresse_postale'
541 )
542 # adresse physique
543 adresse_physique_precision_avant = models.CharField(
544 max_length=255, blank=True
545 )
546 adresse_physique_no = models.CharField(max_length=30, blank=True)
547 adresse_physique_rue = models.CharField(max_length=255, blank=True)
548 adresse_physique_bureau = models.CharField(max_length=255, blank=True)
549 adresse_physique_precision = models.CharField(max_length=255, blank=True)
550 adresse_physique_ville = models.CharField(max_length=255)
551 adresse_physique_code_postal = models.CharField(max_length=30, blank=True)
552 adresse_physique_code_postal_avant_ville = models.NullBooleanField()
553 adresse_physique_region = models.CharField(max_length=255, blank=True)
554 adresse_physique_pays = models.ForeignKey(
555 'references.Pays', to_field='code',
556 db_column='adresse_physique_pays',
557 related_name='impl_adresse_physique'
558 )
559 # autres coordonnées
560 telephone = models.CharField(max_length=255, blank=True)
561 telephone_interne = models.CharField(max_length=255, blank=True)
562 fax = models.CharField(max_length=255, blank=True)
563 fax_interne = models.CharField(max_length=255, blank=True)
564 courriel = models.EmailField(blank=True)
565 courriel_interne = models.EmailField(blank=True)
566 url = models.URLField(verify_exists=False, max_length=255, blank=True)
567 # traitement
568 statut = models.IntegerField(choices=STATUT_CHOICES)
569 date_ouverture = models.DateField(null=True, blank=True)
570 date_inauguration = models.DateField(null=True, blank=True)
571 date_extension = models.DateField(null=True, blank=True)
572 date_fermeture = models.DateField(null=True, blank=True)
573 hebergement_etablissement = models.CharField(max_length=255, blank=True)
574 hebergement_convention = models.NullBooleanField()
575 hebergement_convention_date = models.DateField(null=True, blank=True)
576 remarque = models.TextField()
577 commentaire = models.CharField(max_length=255, blank=True)
578 # meta
579 modif_date = models.DateField()
580
581 class Managers:
582
583 class Ouvertes(ActifsManager):
584
585 def get_query_set(self):
586 return super(Implantation.Managers.Ouvertes, self) \
587 .get_query_set() \
588 .filter(statut=1)
589
590 objects = ActifsManager()
591 ouvertes = Managers.Ouvertes()
592
593 class Meta:
594 db_table = u'ref_implantation'
595 ordering = ['nom']
596 managed = MANAGED
597
598 def __unicode__(self):
599 return "%s (%d)" % (self.nom, self.id)
600
601
602 class Pays(ActifsModel):
603 """
604 Pays (donnée de référence, source: SQI).
605
606 Liste AUF basée sur la liste ISO-3166-1.
607 """
608 code = models.CharField(max_length=2, unique=True)
609 code_iso3 = models.CharField(max_length=3, unique=True)
610 nom = models.CharField(max_length=255)
611 region = models.ForeignKey('references.Region', db_column='region')
612 code_bureau = models.ForeignKey('references.Bureau', to_field='code',
613 db_column='code_bureau', blank=True,
614 null=True)
615 nord_sud = models.CharField(max_length=255, blank=True, null=True)
616 developpement = models.CharField(max_length=255, blank=True, null=True)
617 monnaie = models.CharField(max_length=255, blank=True, null=True)
618
619 class Meta:
620 db_table = u'ref_pays'
621 ordering = ['nom']
622 verbose_name = u"pays"
623 verbose_name_plural = u"pays"
624 managed = MANAGED
625
626 def __unicode__(self):
627 return "%s (%s)" % (self.nom, self.code)
628
629
630 class _Etablissement(ActifsModel):
631 """
632 Superclasse pour les modèles ``Etablissement`` et ``EtablissementBase``
633 """
634 MEMBRE_STATUT_CHOICES = (
635 ('T', 'Titulaire'),
636 ('A', 'Associé'),
637 ('C', 'Candidat'),
638 )
639 QUALITE_CHOICES = (
640 ('ESR', "Établissement d'enseignement supérieur et de recherche"),
641 ('CIR', "Centre ou institution de recherche"),
642 ('RES', "Réseau"),
643 )
644
645 # Infos de base
646 nom = models.CharField(max_length=255)
647 sigle = models.CharField(max_length=16, blank=True)
648 pays = models.ForeignKey(
649 'references.Pays', to_field='code', db_column='pays',
650 related_name='+'
651 )
652 region = models.ForeignKey(
653 'references.Region', db_column='region', blank=True, null=True,
654 related_name='+', verbose_name='région'
655 )
656 implantation = models.ForeignKey(
657 'references.Implantation', db_column='implantation',
658 related_name='+', blank=True, null=True
659 )
660 description = models.TextField(blank=True)
661 historique = models.TextField(blank=True)
662
663 # Membership
664 membre = models.BooleanField()
665 membre_adhesion_date = models.DateField(null=True, blank=True,
666 verbose_name="date d'adhésion")
667 statut = models.CharField(max_length=1, choices=MEMBRE_STATUT_CHOICES,
668 blank=True, null=True)
669 qualite = models.CharField(max_length=3, choices=QUALITE_CHOICES,
670 verbose_name="qualité", blank=True,
671 null=True)
672
673 # Responsable
674 responsable_genre = models.CharField(
675 max_length=1, blank=True, verbose_name='genre'
676 )
677 responsable_nom = models.CharField(
678 max_length=255, blank=True, verbose_name='nom'
679 )
680 responsable_prenom = models.CharField(
681 max_length=255, blank=True, verbose_name='prénom'
682 )
683 responsable_fonction = models.CharField(
684 max_length=255, blank=True, verbose_name='fonction'
685 )
686
687 # Adresse
688 adresse = models.CharField(max_length=255, blank=True)
689 code_postal = models.CharField(max_length=20, blank=True,
690 verbose_name='code postal')
691 cedex = models.CharField(max_length=20, blank=True, verbose_name='CEDEX')
692 ville = models.CharField(max_length=255, blank=True)
693 province = models.CharField(max_length=255, blank=True)
694 telephone = models.CharField(max_length=255, blank=True,
695 verbose_name='téléphone')
696 fax = models.CharField(max_length=255, blank=True)
697 url = models.URLField(verify_exists=False, max_length=255, null=True,
698 blank=True, verbose_name='URL')
699
700 # Meta-données
701 date_modification = models.DateField(verbose_name='date de modification',
702 blank=True, null=True)
703 commentaire = models.TextField(blank=True)
704
705 class Meta:
706 abstract = True
707 ordering = ['pays__nom', 'nom']
708 managed = MANAGED
709
710 def __unicode__(self):
711 return "%s - %s" % (self.pays.nom, self.nom)
712
713
714 class Etablissement(_Etablissement):
715 """
716 Établissement (donnée de référence, source: GDE).
717
718 Un établissement peut être une université, un centre de recherche, un
719 réseau d'établissement... Un établissement peut être membre de l'AUF ou
720 non.
721 """
722 class Meta(_Etablissement.Meta):
723 db_table = u'ref_etablissement'
724 managed = MANAGED
725
726
727 class EtablissementBase(_Etablissement):
728 """
729 Modèle de base pour créer des établissements locaux pouvant être
730 liés à des établissements des données de référence.
731 """
732 ref = models.OneToOneField(Etablissement, blank=True, null=True,
733 related_name='%(app_label)s_%(class)s')
734
735 class Meta:
736 abstract = True
737
738 def save(self, *args, **kwargs):
739 if self.ref and not self.pk:
740 # Nouvel établissement faisant référence à un établissement dans
741 # les références. On copie tous les champs.
742 for f in self.ref._meta.fields:
743 if f.attname != 'id':
744 setattr(self, f.attname, getattr(self.ref, f.attname))
745 super(EtablissementBase, self).save(*args, **kwargs)