web-dev-qa-db-fra.com

Modèles Django - scinder la chaîne en tableau

J'ai un champ de modèle, qui stocke une liste d'URL (oui, je sais, c'est faux) en tant que url1\nurl2\nurl3<...>. Je dois diviser le champ en un tableau dans mon modèle. J'ai donc créé le filtre personnalisé:

@register.filter(name='split')
def split(value, arg):
    return value.split(arg)

Je l'utilise de cette façon:

{% with game.screenshots|split:"\n" as screens %}
        {% for screen in screens %}
            {{ screen }}<br>
        {% endfor %}
    {% endwith %}

mais comme je peux le voir, split ne veut pas fonctionner: le résultat obtenu est le suivant: url1 url2 url3 (avec des sauts de ligne si je regarde le source). Pourquoi?

32
arts777

Django a volontairement laissé de nombreux types de balises de code pour vous dissuader de traiter trop de données dans le modèle. (Malheureusement, les gens ajoutent généralement ces types d’étiquettes.)

Ceci est un exemple parfait de quelque chose qui devrait être dans votre modèle pas dans votre modèle.

class Game(models.Model):
    ...
    def screenshots_as_list(self):
        return self.screenshots.split('\n')

Ensuite, dans votre modèle, vous faites simplement:

{% for screen in game.screenshots_as_list %}
    {{ screen }}<br>
{% endfor %}

Beaucoup plus clair et beaucoup plus facile à travailler.

61
Chris Pratt

La fonctionnalité existe déjà avec linkebreaksbr:

{{ value|linebreaksbr }}

https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#linebreaksbr

12
peterp

Hm, j'ai partiellement résolu ce problème. J'ai changé mon filtre pour:

@register.filter(name='split')
def split(value, arg):
    return value.split('\n')

Pourquoi cela n'a pas fonctionné avec le code original?

4
arts777

Je voulais diviser une liste de mots pour obtenir un nombre de mots, et il s'avère qu'il existe un filtre pour cela:

{{ value|wordcount }}

https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#wordcount

1
ryanjdillon

Indépendamment du point de savoir si votre solution d'origine était la bonne approche, je suppose que le code d'origine ne fonctionnait pas car la signification de l'option \n n'est pas la même dans le code Python et dans le code HTML: dans le code Python, cela signifie la nouvelle ligne d'échappement. caractère, en HTML ce ne sont que les deux caractères séparés \ et n. Donc, passer comme paramètre d'entrée \n du modèle HTML au code Python équivaut à scinder le Chaîne Python \\n: un littéral \ suivi de n.

0