Exemple #1
0
 def html(self, tags=True, pretty_title=False):
     url = None if not tags else self.get_absolute_url()
     conservation = hlp(self.lieu_conservation,
                        ugettext('Lieu de conservation'), tags)
     if self.ancrage.date or self.ancrage.date_approx:
         ancrage = hlp(self.ancrage.html(tags, caps=False), ugettext('date'))
     else:
         ancrage = None
     if self.cote:
         conservation += f", {hlp(self.cote, 'cote', tags)}"
     if self.titre:
         l = [cite(self.titre, tags)]
         if self.numero:
             l.append(self.no())
         if ancrage is not None:
             l.append(ancrage)
         if self.folio:
             l.append(hlp(self.f(), ugettext('folio'), tags))
         if self.page:
             l.append(hlp(self.p(), ugettext('page'), tags))
         if self.lieu_conservation:
             l[-1] += f' ({conservation})'
     else:
         l = [conservation]
         if ancrage is not None:
             l.append(ancrage)
     l = (l[0], small(str_list(l[1:]), tags=tags)) if pretty_title else l
     out = str_list(l)
     return mark_safe(href(url, out, tags))
Exemple #2
0
 def caracteristiques_iterator(self, tags=False):
     if self.numero:
         yield ugettext('n° %s') % self.numero
     if self.coupe:
         yield hlp(ugettext('en %s') % self.coupe, ugettext('coupe'), tags)
     if self.incipit:
         yield hlp(ugettext('« %s »') % self.incipit,
                   ugettext('incipit'), tags)
     # On ajoute uniquement le tempo s’il n’y a pas besoin de lui dans le
     # titre non significatif, c’est-à-dire s’il y a déjà un genre.
     if self.tempo and self.genre_id is not None:
         yield hlp(self.tempo, ugettext('Tempo'), tags)
     if self.tonalite:
         gamme, note, alteration = self.tonalite
         gamme = GAMMES.get(gamme, '')
         note = self.NOTES[note]
         alteration = self.ALTERATIONS[alteration]
         tonalite = ugettext('en %s') % str_list(
             (em(note, tags), alteration, gamme), ' ')
         yield tonalite
     if self.sujet:
         yield hlp(ugettext('sur %s') % self.sujet, ugettext('sujet'), tags)
     if self.arrangement is not None:
         yield f'({self.get_arrangement_display()})'
     if self.surnom:
         yield hlp(f'({self.surnom})', ugettext('surnom'), tags)
     if self.nom_courant:
         yield hlp(self.nom_courant, ugettext('nom courant'), tags)
     if self.opus:
         yield hlp(ugettext('op. %s') % self.opus, ugettext('opus'), tags)
     if self.ict:
         yield hlp(self.ict,
                   ugettext('Indice de Catalogue Thématique'), tags)
Exemple #3
0
 def html(self, tags=True, auteurs=True, titre=True, descr=True,
          ancestors=True, ancestors_links=False, links=True,
          show_type_extrait=True):
     l = []
     if auteurs:
         l.append(self.auteurs_html(tags=tags))
     if titre:
         if ancestors:
             l.append(self.get_referent_ancestors_html(
                 tags=tags, links=ancestors_links))
         if self.has_titre_significatif():
             titre_complet = cite(self.get_titre_significatif(), tags=tags)
         else:
             titre_complet = self.get_titre_non_significatif(
                 tags=tags,
                 caps=(self.type_extrait is None
                       or self.type_extrait in self.TYPES_EXTRAIT_CACHES))
         extrait = capfirst(self.get_extrait(show_type=show_type_extrait))
         if extrait:
             if titre_complet:
                 titre_complet = f'{extrait} {titre_complet}'
             elif self.type_extrait not in self.TYPES_EXTRAIT_CACHES:
                 titre_complet = extrait
         url = None if not tags else self.get_absolute_url()
         l.append(href(url, titre_complet, tags & links))
     if descr:
         l.append(self.get_description(tags=tags))
     return mark_safe(str_list(l))
Exemple #4
0
 def caracteristiques_iterator(self, tags=False):
     if self.numero:
         yield ugettext('n° %s') % self.numero
     if self.coupe:
         yield hlp(ugettext('en %s') % self.coupe, ugettext('coupe'), tags)
     if self.incipit:
         yield hlp(
             ugettext('« %s »') % self.incipit, ugettext('incipit'), tags)
     # On ajoute uniquement le tempo s’il n’y a pas besoin de lui dans le
     # titre non significatif, c’est-à-dire s’il y a déjà un genre.
     if self.tempo and self.genre_id is not None:
         yield hlp(self.tempo, ugettext('Tempo'), tags)
     if self.tonalite:
         gamme, note, alteration = self.tonalite
         gamme = GAMMES.get(gamme, '')
         note = self.NOTES[note]
         alteration = self.ALTERATIONS[alteration]
         tonalite = ugettext('en %s') % str_list(
             (em(note, tags), alteration, gamme), ' ')
         yield tonalite
     if self.sujet:
         yield hlp(ugettext('sur %s') % self.sujet, ugettext('sujet'), tags)
     if self.arrangement is not None:
         yield f'({self.get_arrangement_display()})'
     if self.surnom:
         yield hlp(f'({self.surnom})', ugettext('surnom'), tags)
     if self.nom_courant:
         yield hlp(self.nom_courant, ugettext('nom courant'), tags)
     if self.opus:
         yield hlp(ugettext('op. %s') % self.opus, ugettext('opus'), tags)
     if self.ict:
         yield hlp(self.ict, ugettext('Indice de Catalogue Thématique'),
                   tags)
Exemple #5
0
        def standard(main, prenoms):
            particule = self.get_particule(naissance=(designation == 'B'),
                                           lon=lon)

            l = []
            if nom and not prenoms:
                l.append(titre)
            l.append(main)
            if show_prenoms and (prenoms or particule and not lon):
                if lon:
                    l.insert(max(len(l) - 1, 0), prenoms)
                else:
                    if prenoms:
                        prenoms = abbreviate(prenoms, tags=tags, enabled=abbr)
                    if particule:
                        particule = sc(particule, tags)
                    prenom_and_particule = (f'{prenoms} {particule}'
                                            if prenoms and particule
                                            else (prenoms or particule))
                    l.append(f'({prenom_and_particule})')
            out = str_list(l, ' ')
            if pseudonyme:
                alias = (ugettext('dite') if self.is_feminin()
                         else ugettext('dit'))
                out += f' {alias}\u00A0{pseudonyme}'
            return out
Exemple #6
0
 def html(self,
          tags=True,
          auteurs=True,
          titre=True,
          descr=True,
          ancestors=True,
          ancestors_links=False,
          links=True,
          show_type_extrait=True):
     l = []
     if auteurs:
         l.append(self.auteurs_html(tags=tags))
     if titre:
         if ancestors:
             l.append(
                 self.get_referent_ancestors_html(tags=tags,
                                                  links=ancestors_links))
         if self.has_titre_significatif():
             titre_complet = cite(self.get_titre_significatif(), tags=tags)
         else:
             titre_complet = self.get_titre_non_significatif(
                 tags=tags,
                 caps=(self.type_extrait is None
                       or self.type_extrait in self.TYPES_EXTRAIT_CACHES))
         extrait = capfirst(self.get_extrait(show_type=show_type_extrait))
         if extrait:
             if titre_complet:
                 titre_complet = f'{extrait} {titre_complet}'
             elif self.type_extrait not in self.TYPES_EXTRAIT_CACHES:
                 titre_complet = extrait
         url = None if not tags else self.get_absolute_url()
         l.append(href(url, titre_complet, tags & links))
     if descr:
         l.append(self.get_description(tags=tags))
     return mark_safe(str_list(l))
Exemple #7
0
 def get_description(self, tags=True):
     l = []
     if self.has_titre_significatif():
         l.append(self.get_titre_non_significatif(tags=tags))
     caracteristiques = list(self.caracteristiques_iterator(tags=tags))
     if self.has_titre_non_significatif():
         # La première caractéristique est utilisée dans le titre non
         # significatif.
         caracteristiques = caracteristiques[1:]
     l.extend(caracteristiques)
     return str_list(l, infix=' ')
Exemple #8
0
 def get_description(self, tags=True):
     l = []
     if self.has_titre_significatif():
         l.append(self.get_titre_non_significatif(tags=tags))
     caracteristiques = list(self.caracteristiques_iterator(tags=tags))
     if self.has_titre_non_significatif():
         # La première caractéristique est utilisée dans le titre non
         # significatif.
         caracteristiques = caracteristiques[1:]
     l.extend(caracteristiques)
     return str_list(l, infix=' ')
Exemple #9
0
 def moment_str(self, tags=True, short=False):
     l = []
     date = self.date_str(tags, short)
     heure = self.heure_str()
     pat_date = (ugettext('%(date)s') if self.has_date and self.date
                 else ugettext('%(date)s'))
     pat_heure = (ugettext('à %(heure)s') if self.has_heure and self.heure
                  else ugettext('%(heure)s'))
     l.append(pat_date % {'date': date})
     l.append(pat_heure % {'heure': heure})
     return str_list(l, ' ')
Exemple #10
0
 def moment_str(self, tags=True, short=False):
     l = []
     date = self.date_str(tags, short)
     heure = self.heure_str()
     pat_date = (ugettext('%(date)s') if self.has_date and self.date
                 else ugettext('%(date)s'))
     pat_heure = (ugettext('à %(heure)s') if self.has_heure and self.heure
                  else ugettext('%(heure)s'))
     l.append(pat_date % {'date': date})
     l.append(pat_heure % {'heure': heure})
     return str_list(l, ' ')
Exemple #11
0
    def get_titre_non_significatif(self, tags=True, caps=False):
        if not self.has_titre_non_significatif():
            return ''
        if self.genre is None:
            assert self.tempo != ''
            l = [capfirst(self.tempo) if caps else self.tempo]
        else:
            l = [capfirst(self.genre.nom) if caps else self.genre.nom]
        if not self.has_titre_significatif():
            l.append(self.get_pupitres_str(tags=False, solistes=True))
        l.append(next(self.caracteristiques_iterator(tags=tags), None))

        return str_list(l, infix=' ')
Exemple #12
0
    def get_titre_non_significatif(self, tags=True, caps=False):
        if not self.has_titre_non_significatif():
            return ''
        if self.genre is None:
            assert self.tempo != ''
            l = [capfirst(self.tempo) if caps else self.tempo]
        else:
            l = [capfirst(self.genre.nom) if caps else self.genre.nom]
        if not self.has_titre_significatif():
            l.append(self.get_pupitres_str(tags=False, solistes=True))
        l.append(next(self.caracteristiques_iterator(tags=tags), None))

        return str_list(l, infix=' ')
Exemple #13
0
    def html(self, tags=True):
        relache = ''
        circonstance = ''
        if self.circonstance:
            circonstance = hlp(self.circonstance, ugettext('circonstance'),
                               tags)
        if self.relache:
            relache = microdata(ugettext('Relâche'), 'eventType', tags=tags)

        lieu = microdata(self.debut.lieu_str(tags), 'location', tags=tags)

        return mark_safe(
            str_list((lieu, circonstance, self.debut.heure_str(), relache)))
Exemple #14
0
 def html(self, tags=True, pretty_title=False, link=True):
     url = None if not tags else self.get_absolute_url()
     conservation = hlp(self.lieu_conservation,
                        ugettext('Lieu de conservation'), tags)
     if self.ancrage.date or self.ancrage.date_approx:
         ancrage = hlp(self.ancrage.html(tags, caps=False),
                       ugettext('date'))
     else:
         ancrage = None
     if self.cote:
         conservation += f", {hlp(self.cote, 'cote', tags)}"
     if self.titre:
         l = [cite(self.titre, tags)]
         if self.numero:
             l.append(self.no())
         if ancrage is not None:
             l.append(ancrage)
         if self.lieu_conservation:
             l[-1] += f' ({conservation})'
     else:
         l = [conservation]
         if ancrage is not None:
             l.append(ancrage)
     if self.folio:
         l.append(hlp(self.f(), ugettext('folio'), tags))
     if self.page:
         l.append(hlp(self.p(), ugettext('page'), tags))
     if self.parent is not None:
         l.insert(
             0,
             self.parent.html(tags=tags,
                              pretty_title=pretty_title,
                              link=pretty_title))
     l = (l[0], small(str_list(l[1:]), tags=tags)) if pretty_title else l
     out = str_list(l)
     if link:
         return mark_safe(href(url, out, tags))
     return out
Exemple #15
0
    def html(self, tags=True):
        relache = ''
        circonstance = ''
        if self.circonstance:
            circonstance = hlp(self.circonstance, ugettext('circonstance'),
                               tags)
        if self.relache:
            relache = microdata(ugettext('Relâche'), 'eventType', tags=tags)

        lieu = microdata(self.debut.lieu_str(tags), 'location',
                         tags=tags)

        return mark_safe(str_list((lieu, circonstance,
                                   self.debut.heure_str(), relache)))
Exemple #16
0
 def html(self, tags=True, caps=False):
     l = []
     first = True
     for c in self:
         valeur = c.valeur
         if first and caps:
             valeur = capfirst(valeur)
             first = False
         valeur = mark_safe(valeur)
         if c.type:
             l.append(hlp(valeur, c.type, tags=tags))
         else:
             l.append(valeur)
     return mark_safe(str_list(l))
Exemple #17
0
 def html(self, tags=True, caps=False):
     l = []
     first = True
     for c in self:
         valeur = c.valeur
         if first and caps:
             valeur = capfirst(valeur)
             first = False
         valeur = mark_safe(valeur)
         if c.type:
             l.append(hlp(valeur, c.type, tags=tags))
         else:
             l.append(valeur)
     return mark_safe(str_list(l))
Exemple #18
0
 def html(self, tags=True, short=False, caps=True):
     out = str_list((self.lieu_str(tags, short),
                     self.moment_str(tags, short)))
     if caps:
         return capfirst(out)
     return out
Exemple #19
0
 def html(self, tags=True, short=False, caps=True):
     out = str_list((self.lieu_str(tags, short),
                     self.moment_str(tags, short)))
     if caps:
         return capfirst(out)
     return out
Exemple #20
0
 def interpretes_html(self):
     return str_list([i.html() for i in self.interpretes()])
Exemple #21
0
class Oeuvre(TreeModelMixin, AutoriteModel, UniqueSlugModel):
    prefixe_titre = CharField(_('article'), max_length=20, blank=True)
    titre = CharField(_('titre'), max_length=200, blank=True, db_index=True)
    coordination = CharField(_('coordination'),
                             max_length=20,
                             blank=True,
                             db_index=True)
    prefixe_titre_secondaire = CharField(_('article'),
                                         max_length=20,
                                         blank=True)
    titre_secondaire = CharField(_('titre secondaire'),
                                 max_length=200,
                                 blank=True,
                                 db_index=True)
    genre = ForeignKey('GenreDOeuvre',
                       related_name='oeuvres',
                       blank=True,
                       null=True,
                       verbose_name=_('genre'),
                       on_delete=PROTECT)
    numero = NumberCharField(
        _('numéro'),
        max_length=10,
        blank=True,
        db_index=True,
        validators=[
            RegexValidator(
                r'^[\d\w\-]+$',
                _('Vous ne pouvez saisir que des chiffres, '
                  'lettres non accentuées et tiret, '
                  'le tout sans espace.'))
        ],
        help_text=_(
            'Exemple : « 5 » pour symphonie n° 5, « 7a » pour valse n° 7 a, '
            'ou encore « 3-7 » pour sonates n° 3 à 7. '
            '<strong>Ne pas confondre avec le sous-numéro d’opus.</strong>'))
    coupe = CharField(
        _('coupe'),
        max_length=100,
        blank=True,
        db_index=True,
        validators=[
            RegexValidator(
                r'^\D+$',
                _('Vous devez saisir les quantités '
                  'en toutes lettres.'))
        ],
        help_text=_('Exemple : « trois actes » pour un opéra en trois actes.'))
    indeterminee = BooleanField(
        _('indéterminée'),
        default=False,
        help_text=_(
            'Cocher si l’œuvre n’est pas identifiable, par exemple '
            'un quatuor de Haydn, sans savoir lequel. '
            '<strong>Ne pas utiliser pour un extrait indéterminé</strong>, '
            'sélectionner plutôt dans le programme l’œuvre dont il est tiré '
            'et joindre une caractéristique le décrivant '
            '(« un air », « un mouvement », etc.).'))
    incipit = CharField(
        _('incipit'),
        max_length=100,
        blank=True,
        db_index=True,
        help_text=_('Exemple : « Belle nuit, ô nuit d’amour » pour le n° 13 '
                    'de l’acte III des <em>Contes d’Hoffmann</em> '
                    'd’Offenbach.'))
    tempo = CharField(
        _('tempo'),
        max_length=50,
        blank=True,
        db_index=True,
        help_text=_('Exemple : « Largo », « Presto ma non troppo », etc. '
                    'Ne pas saisir d’indication métronomique.'))
    NOTES = NOTES
    ALTERATIONS = ALTERATIONS
    GAMMES = GAMMES
    TONALITES = [(f'{gamme_k}{note_k}{alter_k}',
                  _(str_list((note_v, alter_v, gamme_v), ' ')))
                 for gamme_k, gamme_v in GAMMES.items()
                 for note_k, note_v in NOTES.items()
                 for alter_k, alter_v in ALTERATIONS.items()]
    tonalite = CharField(_('tonalité'),
                         max_length=3,
                         choices=TONALITES,
                         blank=True,
                         db_index=True)
    sujet = CharField(
        _('sujet'),
        max_length=80,
        blank=True,
        help_text=_(
            'Exemple : « un thème de Beethoven » pour une variation sur un '
            'thème de Beethoven, « des motifs de '
            '&lt;em&gt;Lucia di Lammermoor&lt;/em&gt; » pour une fantaisie '
            'sur des motifs de <em>Lucia di Lammermoor</em> '
            '(&lt;em&gt; et &lt;/em&gt; sont les balises HTML '
            'pour mettre en emphase).'))
    TRANSCRIPTION = 1
    ORCHESTRATION = 2
    ARRANGEMENTS = ((TRANSCRIPTION, _('transcription')), (ORCHESTRATION,
                                                          _('orchestration')))
    arrangement = PositiveSmallIntegerField(_('arrangement'),
                                            choices=ARRANGEMENTS,
                                            blank=True,
                                            null=True,
                                            db_index=True)
    surnom = CharField(_('surnom'),
                       max_length=50,
                       blank=True,
                       db_index=True,
                       help_text=_(
                           'Exemple : « Jupiter » pour la symphonie n° 41 '
                           'de Mozart.'))
    nom_courant = CharField(
        _('nom courant'),
        max_length=70,
        blank=True,
        db_index=True,
        help_text=_('Exemple : « barcarolle » pour le n° 13 de l’acte III des '
                    '<em>Contes d’Hoffmann</em> d’Offenbach.'))
    opus = CharField(
        _('opus'),
        max_length=6,
        blank=True,
        db_index=True,
        validators=[
            RegexValidator(
                r'^[\d\w\-/]+$',
                _('Vous ne pouvez saisir que des chiffres, '
                  'lettres non accentuées, tiret '
                  'et barre oblique, le tout sans espace.'))
        ],
        help_text=_('Exemple : « 12 » pour op. 12, « 27/3 » pour op. 27 n° 3, '
                    '« 8b » pour op. 8 b, ou encore « 12-15 » '
                    'pour op. 12 à 15.'))
    ict = CharField(_('ICT'),
                    max_length=25,
                    blank=True,
                    db_index=True,
                    help_text=_(
                        'Indice de Catalogue Thématique. Exemple : « RV 42 », '
                        '« K. 299d » ou encore « Hob. XVI:24 ».'))
    CREATION_TYPES = (
        (1, _('genèse (composition, écriture, etc.)')),
        (2, _('première mondiale')),
        (3, _('première édition')),
    )
    creation_type = PositiveSmallIntegerField(_('type de création'),
                                              choices=CREATION_TYPES,
                                              null=True,
                                              blank=True)
    creation = AncrageSpatioTemporel(verbose_name=_('création'))
    ORDERING = ('type_extrait', 'numero_extrait', 'titre', 'genre', 'numero',
                'coupe', 'incipit', 'tempo', 'tonalite', 'sujet',
                'arrangement', 'surnom', 'nom_courant', 'opus', 'ict')
    extrait_de = ForeignKey('self',
                            null=True,
                            blank=True,
                            related_name='enfants',
                            verbose_name=_('extrait de'),
                            on_delete=CASCADE)
    path = PathField(order_by=ORDERING, db_index=True)
    ACTE = 1
    TABLEAU = 2
    SCENE = 3
    MORCEAU = 4
    PARTIE = 5
    LIVRE = 6
    ALBUM = 7
    VOLUME = 8
    CAHIER = 9
    ORDRE = 10
    MOUVEMENT = 11
    PIECE = 12
    SERIE = 13
    TYPES_EXTRAIT_ROMAINS = (ACTE, LIVRE, ORDRE)
    TYPES_EXTRAIT_CACHES = (MORCEAU, MOUVEMENT, PIECE)
    TYPES_EXTRAIT = (
        (ACTE, _('acte')),
        (TABLEAU, _('tableau')),
        (SCENE, _('scène')),
        (MORCEAU, _('morceau chanté')),
        (PARTIE, _('partie')),
        (LIVRE, _('livre')),
        (ALBUM, _('album')),
        (VOLUME, _('volume')),
        (CAHIER, _('cahier')),
        (ORDRE, _('ordre')),
        (MOUVEMENT, _('mouvement')),
        (PIECE, _('pièce de recueil')),
        (SERIE, _('série')),
    )
    type_extrait = PositiveSmallIntegerField(_('type d’extrait'),
                                             choices=TYPES_EXTRAIT,
                                             blank=True,
                                             null=True,
                                             db_index=True)
    NUMERO_EXTRAIT_PATTERN = r'^([1-9]\d*)([^\d\.\-]*)$'
    NUMERO_EXTRAIT_RE = re.compile(NUMERO_EXTRAIT_PATTERN)
    numero_extrait = NumberCharField(
        _('numéro d’extrait'),
        max_length=10,
        blank=True,
        db_index=True,
        help_text=_(
            'Le numéro de l’extrait au sein de l’œuvre, par exemple « 3 » '
            'pour le 3<sup>e</sup> mouvement d’un concerto, « 4 » pour '
            'l’acte IV d’un opéra, ou encore « 12b ».'),
        validators=[
            RegexValidator(
                NUMERO_EXTRAIT_PATTERN,
                _('Vous devez saisir un nombre en chiffres arabes '
                  'éventellement suivi de lettres.'))
        ])
    filles = ManyToManyField('self',
                             through='ParenteDOeuvres',
                             related_name='meres',
                             symmetrical=False,
                             blank=True,
                             verbose_name=_('filles'))

    objects = OeuvreManager()

    class Meta(object):
        verbose_name = _('œuvre')
        verbose_name_plural = _('œuvres')
        ordering = ('path', )
        permissions = (('can_change_status', _('Peut changer l’état')), )

    @staticmethod
    def invalidated_relations_when_saved(all_relations=False):
        relations = (
            'enfants',
            'elements_de_programme',
        )
        if all_relations:
            relations += (
                'dossiers',
                'filles',
            )
        return relations

    @permalink
    def get_absolute_url(self):
        return 'oeuvre_detail', [self.slug]

    @permalink
    def permalien(self):
        return 'oeuvre_permanent_detail', [self.pk]

    def link(self):
        return self.html(tags=True,
                         auteurs=False,
                         titre=True,
                         descr=True,
                         ancestors=True)

    link.short_description = _('lien')
    link.allow_tags = True

    def get_extrait(self, show_type=True):
        if not self.type_extrait or not self.numero_extrait:
            return ''
        match = self.NUMERO_EXTRAIT_RE.match(self.numero_extrait)
        if match is None:
            return ''
        digits, suffix = match.groups()
        if self.type_extrait in self.TYPES_EXTRAIT_ROMAINS:
            digits = to_roman(int(digits))
        out = f'{digits}{suffix}'
        if self.type_extrait == self.MORCEAU:
            out = ugettext('№ ') + out
        elif self.type_extrait in (self.MOUVEMENT, self.PIECE):
            out += '.'
        elif show_type:
            return f'{self.get_type_extrait_display()} {out}'
        return out

    def caracteristiques_iterator(self, tags=False):
        if self.numero:
            yield ugettext('n° %s') % self.numero
        if self.coupe:
            yield hlp(ugettext('en %s') % self.coupe, ugettext('coupe'), tags)
        if self.incipit:
            yield hlp(
                ugettext('« %s »') % self.incipit, ugettext('incipit'), tags)
        # On ajoute uniquement le tempo s’il n’y a pas besoin de lui dans le
        # titre non significatif, c’est-à-dire s’il y a déjà un genre.
        if self.tempo and self.genre_id is not None:
            yield hlp(self.tempo, ugettext('Tempo'), tags)
        if self.tonalite:
            gamme, note, alteration = self.tonalite
            gamme = GAMMES.get(gamme, '')
            note = self.NOTES[note]
            alteration = self.ALTERATIONS[alteration]
            tonalite = ugettext('en %s') % str_list(
                (em(note, tags), alteration, gamme), ' ')
            yield tonalite
        if self.sujet:
            yield hlp(ugettext('sur %s') % self.sujet, ugettext('sujet'), tags)
        if self.arrangement is not None:
            yield f'({self.get_arrangement_display()})'
        if self.surnom:
            yield hlp(f'({self.surnom})', ugettext('surnom'), tags)
        if self.nom_courant:
            yield hlp(self.nom_courant, ugettext('nom courant'), tags)
        if self.opus:
            yield hlp(ugettext('op. %s') % self.opus, ugettext('opus'), tags)
        if self.ict:
            yield hlp(self.ict, ugettext('Indice de Catalogue Thématique'),
                      tags)

    def caracteristiques_html(self, tags=True):
        return ' '.join(list(self.caracteristiques_iterator(tags=tags)))

    caracteristiques_html.allow_tags = True
    caracteristiques_html.short_description = _('caractéristiques')

    def get_pupitres_str(self, prefix=True, tags=False, solistes=False):
        if not self.pk:
            return ''
        pupitres = self.pupitres.all()
        if solistes:
            pupitres = [p for p in pupitres if p.soliste]

        if not pupitres:
            return ''
        if not prefix:
            return str_list_w_last([p.html(tags=tags) for p in pupitres])

        pupitres_roles = str_list_w_last([
            p.html(tags=tags) for p in pupitres if p.partie.type == Partie.ROLE
        ])
        pupitres_instruments = str_list_w_last([
            p.html(tags=tags) for p in pupitres
            if p.partie.type == Partie.INSTRUMENT
        ])

        if pupitres_roles:
            out = ugettext('de ') + pupitres_roles
            if pupitres_instruments:
                out += ugettext(' avec ') + pupitres_instruments
            return out
        return ugettext('pour ') + pupitres_instruments

    def pupitres_html(self, prefix=False, tags=True, solistes=False):
        return self.get_pupitres_str(prefix=prefix,
                                     tags=tags,
                                     solistes=solistes)

    @model_method_cached()
    def auteurs_html(self, tags=True):
        return self.auteurs.html(tags)

    auteurs_html.short_description = _('auteur(s)')
    auteurs_html.allow_tags = True
    auteurs_html.admin_order_field = 'auteurs__individu__nom'

    def parentes_in_order(self, relation):
        return getattr(self,
                       relation).order_by('creation_date', 'creation_heure',
                                          'creation_lieu',
                                          'creation_date_approx',
                                          'creation_heure_approx',
                                          'creation_lieu_approx')

    def meres_in_order(self):
        return self.parentes_in_order('meres')

    def filles_in_order(self):
        return self.parentes_in_order('filles')

    @property
    def evenements(self):
        # We use a subquery, otherwise yearly_counts counts the number of
        # program elements instead of events.
        return apps.get_model('libretto', 'Evenement').objects.filter(
            pk__in=apps.get_model('libretto', 'Evenement').objects.filter(
                programme__oeuvre__in=self.get_descendants(include_self=True)))

    def oeuvres_associees(self):
        # TODO: Limiter à ce que l’utilisateur peut voir.
        return (Oeuvre.objects.exclude(pk__in=self.get_descendants(
            include_self=True)).filter(
                elements_de_programme__evenement__programme__oeuvre=self).
                annotate(n=Count('elements_de_programme__evenement')).order_by(
                    '-n', *self._meta.ordering)).distinct()

    def _link_with_number(self):
        return ugettext('œuvre jouée %s fois avec : %s') % (self.n,
                                                            self.link())

    def get_referent_ancestors_html(self, tags=False, links=False):
        if not self.pk or self.extrait_de is None or \
                (self.genre and self.genre.referent):
            return ''
        return self.extrait_de.titre_html(tags=tags,
                                          links=links,
                                          ancestors_links=links,
                                          show_type_extrait=False)

    def has_titre_significatif(self):
        return bool(self.titre)

    def get_titre_significatif(self):
        return (f'{self.prefixe_titre}{self.titre}'
                f'{self.coordination}'
                f'{self.prefixe_titre_secondaire}{self.titre_secondaire}')

    def has_titre_non_significatif(self):
        return self.tempo or self.genre_id is not None

    def get_titre_non_significatif(self, tags=True, caps=False):
        if not self.has_titre_non_significatif():
            return ''
        if self.genre is None:
            assert self.tempo != ''
            l = [capfirst(self.tempo) if caps else self.tempo]
        else:
            l = [capfirst(self.genre.nom) if caps else self.genre.nom]
        if not self.has_titre_significatif():
            l.append(self.get_pupitres_str(tags=False, solistes=True))
        l.append(next(self.caracteristiques_iterator(tags=tags), None))

        return str_list(l, infix=' ')

    def get_description(self, tags=True):
        l = []
        if self.has_titre_significatif():
            l.append(self.get_titre_non_significatif(tags=tags))
        caracteristiques = list(self.caracteristiques_iterator(tags=tags))
        if self.has_titre_non_significatif():
            # La première caractéristique est utilisée dans le titre non
            # significatif.
            caracteristiques = caracteristiques[1:]
        l.extend(caracteristiques)
        return str_list(l, infix=' ')

    @model_method_cached()
    def html(self,
             tags=True,
             auteurs=True,
             titre=True,
             descr=True,
             ancestors=True,
             ancestors_links=False,
             links=True,
             show_type_extrait=True):
        l = []
        if auteurs:
            l.append(self.auteurs_html(tags=tags))
        if titre:
            if ancestors:
                l.append(
                    self.get_referent_ancestors_html(tags=tags,
                                                     links=ancestors_links))
            if self.has_titre_significatif():
                titre_complet = cite(self.get_titre_significatif(), tags=tags)
            else:
                titre_complet = self.get_titre_non_significatif(
                    tags=tags,
                    caps=(self.type_extrait is None
                          or self.type_extrait in self.TYPES_EXTRAIT_CACHES))
            extrait = capfirst(self.get_extrait(show_type=show_type_extrait))
            if extrait:
                if titre_complet:
                    titre_complet = f'{extrait} {titre_complet}'
                elif self.type_extrait not in self.TYPES_EXTRAIT_CACHES:
                    titre_complet = extrait
            url = None if not tags else self.get_absolute_url()
            l.append(href(url, titre_complet, tags & links))
        if descr:
            l.append(self.get_description(tags=tags))
        return mark_safe(str_list(l))

    html.short_description = _('rendu HTML')
    html.allow_tags = True

    def short_html(self, tags=True, links=False):
        return self.html(tags=tags,
                         auteurs=False,
                         titre=True,
                         descr=False,
                         ancestors=False,
                         links=links)

    def titre_html(self,
                   tags=True,
                   links=True,
                   ancestors_links=True,
                   show_type_extrait=True):
        return self.html(tags,
                         auteurs=False,
                         titre=True,
                         descr=False,
                         ancestors=True,
                         ancestors_links=ancestors_links,
                         links=links,
                         show_type_extrait=show_type_extrait)

    titre_html.short_description = _('titre')

    def titre_descr(self, tags=False):
        return self.html(tags=tags,
                         auteurs=False,
                         titre=True,
                         descr=True,
                         ancestors=True)

    def titre_descr_html(self):
        return self.titre_descr(tags=True)

    def description_html(self, tags=True):
        return self.html(tags, auteurs=False, titre=False, descr=True)

    def handle_whitespaces(self):
        match = re.match(r'^,\s*(.+)$', self.coordination)
        v = self.coordination if match is None else match.group(1)
        if v:
            self.coordination = f', {v}'
        for attr in ('prefixe_titre', 'prefixe_titre_secondaire',
                     'coordination'):
            v = getattr(self, attr)
            if v and v[-1] not in (' ', "'", '’'):
                setattr(self, attr, f'{v} ')

    def related_label(self):
        txt = force_text(self)
        auteurs = self.auteurs.html(tags=False)
        if auteurs:
            txt += f' ({auteurs})'
        return txt

    def __str__(self):
        return strip_tags(self.titre_html(False))  # strip_tags car on autorise
        # les rédacteurs à mettre des tags dans les CharFields

    _str = __str__
    _str.short_description = _('œuvre')

    @staticmethod
    def autocomplete_search_fields(add_icontains=True):
        lookups = ('auteurs__individu__nom', 'auteurs__individu__prenoms',
                   'auteurs__individu__pseudonyme', 'auteurs__ensemble__nom',
                   'prefixe_titre', 'titre', 'prefixe_titre_secondaire',
                   'titre_secondaire', 'genre__nom', 'numero', 'coupe',
                   'tempo', 'sujet', 'surnom', 'nom_courant', 'incipit',
                   'opus', 'ict', 'pupitres__partie__nom')
        lookups = [f'{lookup}__unaccent' for lookup in lookups]
        if add_icontains:
            return [f'{lookup}__icontains' for lookup in lookups]
        return lookups
Exemple #22
0
 def membres_html(self):
     return str_list([
         membre.html() for membre in
         self.membres.select_related('individu', 'instrument')])
Exemple #23
0
 def membres_html(self):
     return str_list([
         membre.html() for membre in
         self.membres.select_related('individu', 'instrument')])
Exemple #24
0
 def interpretes_html(self):
     return str_list([i.html() for i in self.interpretes()])