Invalid Filter lors du passage dev/prod

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,

J'ai développé une application que j'ai ensuite deployé. Jusque là pas de soucis. Mais par la suite, j'ai fait évolué cette application et lors de la mise a jour de l'application déployée, j'ai plusieurs "TemplateSyntaxError : Invalid filter" qui sont apparues à l'utilisation de filtre personnalisé Il n'y avait aucun problème dans l'environnement de dev django, mais surtout, j'utilisais deja des filtres custom dont certains sont dans les memes fichiers que les nouveaux qui ne sont pas reconnus. Mes filtres se trouvent dans utils.templatetags.extras. utils est bien déclaré dans le fichier settings et extras contient d'autres filtres qui eux sont reconnus et ne provoquent pas d'erreur. En Dev, j'utilise Linux avec Django. En prod, c'est un serveur Windows 7 avec Apache 2.4 et MySQL 5.6 (avec python 2.7.8 partout) J'ai essayé d'importer et d'essayer mes filtres manuellement avec le shell de django sur le serveur de production, tout fonctionne parfaitement. En debuggant, je me suis rendu compte que Django ne passe pas dans le fichier de mes filtres et n'execute donc pas register=template.Library() En utilisant add_to_builtins() dans urls.py par exemple, le filtre est bien importé.

L'arborescence:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
|project
  |ism
    -__init__.py
    -settings.py (contient ism.utils)
    |utils
      -__init__.py
      |templatetags
        -__init__.py
        -extras.py
  |templates
    |site
      -list.html (contient {% load extras %})

Voila l'erreur exacte:

  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
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
Environment:
Request Method: GET
Request URL: http://localhost:8000/ism/sites/list

Django Version: 1.6
Python Version: 2.7.8
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django_extensions',
 'south',
 'ism.core',
 'ism.supervision',
 'ism.utils')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.middleware.locale.LocaleMiddleware')


Template error:
In template C:\Apache\project\templates\site\list.html, error at line 31
   Invalid filter: 'at_least_one_have_alert'
   21 : 
   22 : 
   23 : {% block content %}
   24 : 
   25 : {% if site_groups %}
   26 : <div class="panel-group" id="sites_list">
   27 :     {% for site_group in site_groups %}
   28 :       <div class="panel panel-default">
   29 :         <div class="panel-heading">
   30 :               <h4 class="panel-title" style="width:50%;">
   31 :                {% if site_group.site_set.all|at_least_one_have_alert %} 
   32 :                <span 
   33 :                     class="glyphicon glyphicon-bell text-danger"
   34 :                     title="{% trans 'At least one site in this group have a unacquired alert' %}">
   35 :                 </span>
   36 :             {% else %}
   37 :                 <span 
   38 :                     class="glyphicon glyphicon-bell text-success"
   39 :                     title="{% trans 'no site in this group have a unacquired alert' %}">
   40 :                 </span>
   41 :             {% endif %}

Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
  139.                 response = response.render()
File "C:\Python27\lib\site-packages\django\template\response.py" in render
  105.             self.content = self.rendered_content
File "C:\Python27\lib\site-packages\django\template\response.py" in rendered_content
  80.         template = self.resolve_template(self.template_name)
File "C:\Python27\lib\site-packages\django\template\response.py" in resolve_template
  56.             return loader.select_template(template)
File "C:\Python27\lib\site-packages\django\template\loader.py" in select_template
  180.             return get_template(template_name)
File "C:\Python27\lib\site-packages\django\template\loader.py" in get_template
  138.     template, origin = find_template(template_name)
File "C:\Python27\lib\site-packages\django\template\loader.py" in find_template
  127.             source, display_name = loader(name, dirs)
File "C:\Python27\lib\site-packages\django\template\loader.py" in __call__
  43.         return self.load_template(template_name, template_dirs)
File "C:\Python27\lib\site-packages\django\template\loader.py" in load_template
  49.             template = get_template_from_string(source, origin, template_name)
File "C:\Python27\lib\site-packages\django\template\loader.py" in get_template_from_string
  149.     return Template(source, origin, name)
File "C:\Python27\lib\site-packages\django\template\base.py" in __init__
  125.         self.nodelist = compile_string(template_string, origin)
File "C:\Python27\lib\site-packages\django\template\base.py" in compile_string
  153.     return parser.parse()
File "C:\Python27\lib\site-packages\django\template\base.py" in parse
  278.                     compiled_result = compile_func(self, token)
File "C:\Python27\lib\site-packages\django\template\loader_tags.py" in do_extends
  215.     nodelist = parser.parse()
File "C:\Python27\lib\site-packages\django\template\base.py" in parse
  278.                     compiled_result = compile_func(self, token)
File "C:\Python27\lib\site-packages\django\template\loader_tags.py" in do_block
  190.     nodelist = parser.parse(('endblock',))
File "C:\Python27\lib\site-packages\django\template\base.py" in parse
  278.                     compiled_result = compile_func(self, token)
File "C:\Python27\lib\site-packages\django\template\defaulttags.py" in do_if
  942.     nodelist = parser.parse(('elif', 'else', 'endif'))
File "C:\Python27\lib\site-packages\django\template\base.py" in parse
  278.                     compiled_result = compile_func(self, token)
File "C:\Python27\lib\site-packages\django\template\defaulttags.py" in do_for
  806.     nodelist_loop = parser.parse(('empty', 'endfor',))
File "C:\Python27\lib\site-packages\django\template\base.py" in parse
  278.                     compiled_result = compile_func(self, token)
File "C:\Python27\lib\site-packages\django\template\defaulttags.py" in do_if
  941.     condition = TemplateIfParser(parser, bits).parse()
File "C:\Python27\lib\site-packages\django\template\defaulttags.py" in __init__
  874.         super(TemplateIfParser, self).__init__(*args, **kwargs)
File "C:\Python27\lib\site-packages\django\template\smartif.py" in __init__
  163.             mapped_tokens.append(self.translate_token(token))
File "C:\Python27\lib\site-packages\django\template\smartif.py" in translate_token
  174.             return self.create_var(token)
File "C:\Python27\lib\site-packages\django\template\defaulttags.py" in create_var
  877.         return TemplateLiteral(self.template_parser.compile_filter(value), value)
File "C:\Python27\lib\site-packages\django\template\base.py" in compile_filter
  360.         return FilterExpression(token, self)
File "C:\Python27\lib\site-packages\django\template\base.py" in __init__
  571.                 filter_func = parser.find_filter(filter_name)
File "C:\Python27\lib\site-packages\django\template\base.py" in find_filter
  366.             raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name)

Exception Type: TemplateSyntaxError at /sites/list
Exception Value: Invalid filter: 'at_least_one_have_alert'

En vous remerciant d'avance.

+0 -0
Staff

J'ai développé une application que j'ai ensuite deployé. Jusque là pas de soucis. Mais par la suite, j'ai fait évolué cette application et lors de la mise a jour de l'application déployée, j'ai plusieurs "TemplateSyntaxError : Invalid filter"

luckyboss1

Visiblement tu l'as déjà déployé une fois et ça marchait bien. Peux-tu nous dire ce que tu as mis à jour dans ton code entre les deux déploiements ?

Auteur du sujet

Alors, Les filtres sont bien déclarés avec register = template.Library(), puis register.filter Dans le meme fichier certains filtres sont utilisés et fonctionnent et d'autres nan. Exemple d'un fichier:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from django import template

register = template.Library()
#Ce filtre provoque un "Invalid Filter"
@register.filter(name='is_about_stream')
def is_about_stream(alert):
    if alert.server_alert_type_id in [4, 8, 9]:
        return True
    return False
#Ce filtre fonctionnre
@register.filter(name='total_unacq')
def total_unacq(alerts):
    total = 0
    for alert in alerts:
        if alert.is_unacq():
            total += 1

    return total

Pour les changements, il y en a eu beaucoup trop pour les lister. Mais globalement, il y a eu des ajout d'app, de filtre, des modifications de model/view… Pas de modification de l'arborescence general du projet

+0 -0
Auteur du sujet

Moi aussi je trouve ca bizarre. Voila :

1
2
3
4
5
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ism.settings")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
+0 -0
Staff

Histoire de bien vérifier, dans ta définition de total_unacq pourrait tu vérifier en rajoutant un print ou un log que cette bien cette fonction, définit dans le meme fichier que is_about_stream, qui est traversé. Il serait étrange qu'un filtre est dispo et pas un autre.

+0 -0
Auteur du sujet

Oui oui,

Depuis hier je l'ai redémarré des dizaines de fois je te rassure ^^

@Christophe, Oui, je viens de verifier, le print dans total_unacq s'affiche bien. Je n'ai pas précisé, mais en relancant sur le windows avec le serveur de dev de django, cela ne fonctionne pas non plus…

EDIT: Ah je rectifie, le print ne s'affiche pas, j'etais encore sur le config de test qui elle fonctionne. Donc, j'ai supprimé les pyc, et la, je constate que le serveur ne m'a pas recompilé tous les fichiers py ? et en particulier celui contenant des nouveau filtres…

Édité par grugru

+0 -0
Staff

Je n'ai pas précisé, mais en relancant sur le windows avec le serveur de dev de django, cela ne fonctionne pas non plus…

luckyboss1

Ah donc ça ne vient pas du serveur distant. Donc visiblement quelque chose cloche dans ton code. J'aurais tendance a demander l'intégralité de ton fichier extras pour vérifier de mes propres yeux ce qui ne colle pas.

Staff

Ah donc ça ne vient pas du serveur distant. Donc visiblement quelque chose cloche dans ton code. J'aurais tendance a demander l'intégralité de ton fichier extras pour vérifier de mes propres yeux ce qui ne colle pas.

Et d'un fichier template qui pose problème.

+0 -0
Auteur du sujet

Bien le probleme semble plus clair puisque aucun fichier pyc n'est recréé quand je les supprime…

Voici le fichier extras.py:

  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
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
from django import template
from django.utils.translation import gettext_lazy as _

from ism.supervision.models import ServerAlert
from ism.supervision.models import ServerStream

register = template.Library()

@register.filter('is_about_stream')
def is_about_stream(alert):
    if alert.server_alert_type_id in [4, 8, 9]:
        return True
    return False

@register.filter('last_alert_is_resolved')
def last_alert_is_resolved(alert):
    """
    if the last alert received for this alert is a resolved alert, 
    return True, else False
    """
    if alert.last_resolution_date == None:
        return False
    else:
        if alert.last_date == alert.last_resolution_date:
            return True
        else:
            return False


@register.filter('at_least_one_have_alert')
def at_least_one_have_alert(sites):
    """
    if at least one site have a unacquired alert, 
    return True, else False
    """
    print 'plop'
    for site in sites:
        if total_unacq(site.server.serveralert_set.all()) > 0:
            return True
    return False

@register.filter('total_unacq')
def total_unacq(alerts):
    """
    Return total alert unacquired
    """
    total = 0
    for alert in alerts:
        if alert.is_unacq():
            total += 1

    return total


@register.filter('sum_unacq_count')
def sum_unacq_count(alerts):
    """
    Return sum of alert count unacquired
    """
    total = 0
    for alert in alerts:
        if alert.is_unacq():
            total += alert.count

    return total


@register.filter('total_processing')
def total_processing(alerts):
    """
    Return total alert processing by users. 
    """
    total = 0
    for alert in alerts:
        if alert.is_pending():
            total += 1

    return total


@register.filter('sum_processing_count')
def sum_processing_count(alerts):
    """
    Return sum of alert count processing by users. 
    """
    total = 0
    for alert in alerts:
        if alert.is_pending():
            total += alert.count

    return total


@register.filter('first_processing_id')
def first_processing_id(alerts):
    """
    Return id of first alert in processing 
    """
    for alert in alerts:
        if alert.is_pending():
            return alert.id
    return 0


@register.filter('get_server_stream')
def get_server_stream(alert_id):
    """
    return stream object concerned by alert with alert_id
    """
    alert = ServerAlert.objects.get(pk=alert_id)
    if ServerStream.objects.filter(remote_stream_id=alert.value_id, server=alert.server).exists():
        return ServerStream.objects.filter(remote_stream_id=alert.value_id, server=alert.server).first()
    else:
        return None


@register.filter('get_alert_type_label')
def get_alert_type_label(type_id):
    """
    return alert type label for the type_id
    """
    print 'test'
    if type_id == 1:
        return _("AutoStart Monitoring")
    elif type_id == 2:
        return _("CPU Usage")
    elif type_id == 3:
        return _("Memory Usage")
    elif type_id == 4:
        return _("Image Obstructed")
    elif type_id == 5:
        return _("Critical Error")
    elif type_id == 6:
        return _("Monitoring State")
    elif type_id == 7:
        return _("Server State")
    elif type_id == 8:
        return _("Video Stream")
    elif type_id == 9:
        return _("Recording Error")
    elif type_id == 10:
        return _("Storage Folder")
    else:
        return _("Unknown")

Dans le template, j'ai écrit quelque chose comme ca. Si je retire juste le if avec le filtre, le reste fonctionne parfaitement.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{% extends "site/base_site.html" %}
{% load i18n %}
{% load extras %}
{% load datetime %}
{% load servers %}
{% if site_groups %}
{% for site_group in site_groups %}
      {% if site_group.site_set.all|at_least_one_have_alert %}
               <span 
                    class="glyphicon glyphicon-bell text-danger"
                    title="{% trans 'At least one site in this group have a unacquired alert' %}">
                </span>
            {% else %}
                <span 
                    class="glyphicon glyphicon-bell text-success"
                    title="{% trans 'no site in this group have a unacquired alert' %}">
        </span>
         {% endif %}
{% endfor %}
{% endif %}

Après suppression, la fonction get_alert_type_label() par exemple utilisée sur une autre page continue de fonctionner parfaitement malgrè l'absence de fichier pyc.

+0 -0
Auteur du sujet

Alors j'ai trouvé le problème, je poste quand meme au cas ou. A cause d'un restructuration du projet, le script de ployment n'avait aps supprimé une ancienne version du fichier pyc située autre part dans le projet qui avait donc des tags qui correspondaient aux nouveaux mais pas tous…

Merci pour le coup de main :)

Édité par grugru

+0 -0
Staff

Ce qui est étrange c'est que normalement les pyc est regénéré dès que les fichiers sources sont plus récents. Il aurait dut les re-générer, sauf si il trouvait les anciens pyc dans l'ancien répertoire avant de trouver les nouvelles sources.

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

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