Django : utiliser un filtre pour en interpréter un autre

Le problème exposé dans ce sujet a été résolu.

Bonjour !

Voilà, depuis quelques temps, j’apprends le langage Python ainsi que l’usage de Django. Pour mes essais, je me suis donc créé un site web basique qui possède, entre autres, une page listant tous les articles enregistrés dans la BDD, écrits depuis l’interface d’administration.

Seulement, cette page ne proposant que du plain-text, j’ai voulu y ajouter la possibilité d’utiliser des filtres. J’ai donc créé un filtre citation qui entoure le texte d’une balise HTML blockquote. Enfin, dans le template affichant un article, j’ai rajouté un filtre faisant le rendu du contenu de cet article. Seulement, ce filtre renvoi systématiquement une erreur Invalid filter: 'citation' s’il est placé avant le filtre linebreaks et une erreur Could not parse some characters: |"Ma super citation."||citation:"Auteur" s’il est placé après.

Je précise que le filtre citation fonctionne parfaitement quand il est intégré de base dans le template.

Y aurait-il quelque chose à modifier dans le filtre ou le template pour prévenir ce comportement ?

Ou, à défaut, est-il possible de "personnaliser" le markdown. Dans l’idéal, j’aimerais me rapprocher des possibilités du zMarkdown de ZdS, pour notamment afficher l’auteur d’une citation (ce que je parviens à faire avec un filtre), ou ajouter des notes de bas de page.

Voici les morceaux de code impliqués. Je précise que ce projet est mon premier et qu’il me sert de "terrain d’essai", il risque d’y avoir quelques énormités dont je ne me rends pas encore compte.

La vue

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def home(request):
    categ = request.GET.get('categorie')
    if not categ:
        articles = Article.objects.all()
        error_type = None
    else:
        try:
            some_category = Categorie.objects.get(nom=categ)
            articles = Article.objects.filter(categorie=some_category)
            error_type = None
        except:
            articles = Article.objects.all()
            error_type = 'wrong_category'
    return render(request, 'blog/home.html', {'derniers_articles': articles, 'error':error_type})

Le template

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{% extends "base.html" %}
{% load blog_extras %}

{% block title %}Liste des articles{% endblock %}

{% block content %}
<p>Voici la liste des articles. Vous pouvez les filtrer selon les catégories suivantes :</p>
{% if error == "wrong_category" %}<p><b>Cette catégorie n'est pas reconnue, désolé.</b></p>{% endif %}
<div class="inline_list">
    <ul>
        <li><a href="{{ request.path }}">Toutes</a></li><li><a href="{{ request.path }}?categorie=Photographie">Photographie</a></li><li><a href="{{ request.path }}?categorie=Général">Général</a></li>
    </ul>
</div>
{% for article in derniers_articles reversed %}
<div class="article">
    <hr align="left">
    <h3>&nbsp;&nbsp;&nbsp;{{ article.titre }}</h3>
    <!-- L'erreur concerne la ligne ci-dessous. !-->
    <!-- La même chose se produit quand j'enlève le filtre truncatewords_html pour afficher l'article en entier. !-->
    <p>{{ article.contenu|truncatewords_html:60|linebreaks|compile }}</p>
    <p><a href="{% url 'blog.views.view_article' article.id %}">Lire la suite</a></p>
</div>
{% empty %}
    <p>Aucun article.</p>
{% endfor %}
{% endblock %}

Le fichier blog_extras.py, contenant les filtres (extrait)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from django.template import Template, Context

@register.filter(is_safe=True)
def compile(texte):
    t = Template(texte)
    c = Context({})
    return t.render(c)

# J'ai aussi tenté de rajouter les deux lignes suivantes
# (selon une suggestion sur StackOverflow, mais sans succès.

register.filter('compile', compile)
register.filter('citation', citation)

Un exemple de contenu d’un article

1
2
3
{{"Longue vie et prospérité."|citation:"Spock"}}

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ullamcorper pulvinar lectus eget tincidunt. Pellentesque rhoncus, justo sagittis condimentum eleifend, neque metus commodo augue, in tempor felis eros eget nunc.

Auriez-vous une idée de la cause de cette erreur ?

Merci d’avance pour votre aide ! :)

rezemika

+0 -0

Merci de ta réponse ! Je viens de tenter les deux.

Avec le safe, il n’y a aucun changement. En revanche, avec {% autoescape off %}, l’erreur est systématiquement Invalid filter: 'citation', quelque soit la position du filtre linebreaks. Serait-ce le filtre citation qui est en cause. Je mets son code ici au cas où.

1
2
3
4
5
6
7
8
9
@register.filter(is_safe=True)
def citation(texte, source=None):
    html = """<blockquote>{}""".format(texte)
    if not source:
        html = html + "</blockquote>"
    else:
        html = html + """<div class="citation_source">{}</div>
            </blockquote>""".format(source)
    return html
+0 -0

Je viens de trouver une astuce (certes pas très propre) pour résoudre le problème. Il fallait aussi charger les filtres dans le plain-text que l’on passe au filtre de rendu. Merci victor. ;)

1
2
3
4
5
@register.filter(is_safe=True)
def compiler(texte):
    t = Template("{% load blog_extras %} " + texte)
    c = Context({})
    return t.render(c)
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte