50 votes

Changement de version de Django par défaut du moteur d'application

Depuis app engine 1.4.2 a été libéré, je reçois des avertissements de ce genre dans mes journaux de production:

Vous utilisez la valeur par défaut de Django version (0.96). La valeur par défaut de Django version va changer dans un App Engine la libération dans le proche avenir. Merci appel use_library() explicitement sélectionnez une version de Django. Pour plus d' d'informations, voir http://code.google.com/appengine/docs/python/tools/libraries.html#Django

Cela se produit sur chaque gestionnaire où j'utilise Django template via le suivant:

from google.appengine.ext.webapp import template

J'aimerais mettre à niveau vers la version 1.2, cependant les liens suivants ne semblent pas très clair sur exactement comment le faire (ou si ça marche à tous):

Le dénominateur commun est d'insérer ceci:

from google.appengine.dist import use_library
use_library('django', '1.2')

Toutefois, dans ce dossier(s) devrait-il être inséré:

  1. Juste en appengine_config.py?
  2. Dans tous les .py fichier qui n' from google.appengine.ext.webapp import template?
  3. Dans tous les .py fichier dans le projet?
  4. Dans 1 et (2 ou 3) ci-dessus, et aussi d'ajouter import appengine_config de ces fichiers?
  5. Dans 3 ou 4, et également ajouter des wrappers autour de fonctions intégrées comme appstats, api à distance, la banque de données de admin, etc?
  6. Quelque chose d'autre?

Merci.

56voto

Saxon Druce Points 9404

Comme décrit par Nick dans les commentaires de systempuntoout réponse, j'ai inséré cette use_library() code à partir d'ici dans chaque gestionnaire que les importations de django (soit directement ou par l'intermédiaire de google.appengine.ext.webapp.template ou même juste django.utils.simplejson):

from google.appengine.dist import use_library
use_library('django', '1.2')

Comme suggéré par Nick, cela a été rendu plus facile par la première refactoring de réduire le nombre de gestionnaires référencé par l'app.yaml (c'est à dire, plus près du scénario 1 décrit ici).

Cependant, j'ai l'appstats builtin configuré, et si j'ai d'abord allé à l' /_ah/appstats après un téléchargement, alors j'obtiens cette erreur:

<'de google.appengine.dist._library.UnacceptableVersionError'>: django 1.2 a été demandé, mais 0.96.4.Aucun n'est déjà en cours d'utilisation

J'ai été en mesure de résoudre ce problème en incluant également l' use_library() code appengine_config.py.

J'ai remarqué que par l'insertion d'un appel à l' use_library() en appengine_config.py, alors qu'il n'était plus nécessaire dans tous mes maîtres. En particulier ceux qui importent google.appengine.ext.webapp.template n'en ont pas besoin, parce que l'importation webapp.template charge appengine_config.py. Le appstats de l'INTERFACE utilisateur importations webapp.template, c'est pourquoi cette résolu le problème.

Cependant, j'ai eu quelques gestionnaires (par exemple json services) qui ne sont pas importés webapp.template, mais ne l'importation django.utils.simplejson. Ces gestionnaires exigent toujours un appel direct à l' use_library(). Si, au contraire, ces gestionnaires sont appelés d'abord sur une nouvelle instance, l' UnacceptableVersionError se produit. Bien que je suis en utilisant appengine_config.py pour configurer appstats, signification, appengine_config.py est appelé à l'instrument, à toutes les demandes, il est appelé trop tard dans le cycle de vie de page pour configurer correctement la bonne version de Django.

Tout cela est apparu à travailler bien au début, mais ensuite j'ai découvert un en arrière de l'incompatibilité entre le nouveau Django 1.2 et le vieux Django 0.96 qui j'avais été en utilisant. Mon projet de construction est comme ceci:

root
+- admin
|  +- page_admin.html
+- page_base.html

Avec Django, 0.96, avoir de la suite dans page_admin.html a bien fonctionné:

{% extends "../page_base.html" %}

Avec Django 1.2, j'ai eu cette erreur:

TemplateDoesNotExist: ../page_base.html

Le changement dans Django 1.2 semble que par défaut, Django ne permet pas le chargement des modèles qui sont au-dessus du modèle d'origine du répertoire.

Une solution de contournement pour ce qui est décrit ici, mais cette approche ne pouvait pas fonctionner pour moi, car il exige que les modèles à être dans un des modèles de sous-répertoire.

La solution c'est d'installer un settings.py le fichier, définissez l' TEMPLATE_DIRS paramètre le répertoire racine du projet, et puis changer l' extends balise juste référence "page_base.html", comme décrit ici. Cependant, j'ai rencontré deux problèmes en essayant de le faire.

J'ai été en utilisant le code recommandé de rendre mon modèle, c'est à dire:

template_values = { ... }
path = os.path.join(os.path.dirname(__file__), 'page_admin.html')
self.response.out.write(template.render(path, template_values))

Le premier problème est qu' template.render() remplace l' TEMPLATE_DIRS réglage pour le répertoire du modèle en cours de rendu. La solution est donc le code suivant:

template_values = { ... }
path = os.path.join(os.path.dirname(__file__), 'page_admin.html')
template_file = open(path) 
compiled_template = template.Template(template_file.read()) 
template_file.close()  
self.response.out.write(compiled_template.render(template.Context(template_values))) 

Un inconvénient de cette approche est que, template.render() caches de la compilation des templates, alors que ce code ne fonctionne pas (bien que ce ne serait pas difficile d'en rajouter).

Pour configurer l' TEMPLATE_DIRS réglage, j'ai ajouté un settings.py mon projet:

PROJECT_ROOT = os.path.dirname(__file__) 
TEMPLATE_DIRS = (PROJECT_ROOT,)

Et puis dans tous mes maîtres-chiens, avant de l' use_library() code, j'ai mis l' DJANGO_SETTINGS_MODULE comme décrit ici:

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' 

Le deuxième problème est que cela n'a pas fonctionné - le fichier de paramètres n'était pas chargé, et donc l' TEMPLATE_DIRS était vide.

Django paramètres sont chargés de l'spécifiée settings.py paresseusement, la première fois qu'ils sont accessibles. Le problème, c'est que l'importation d' webapp.template des appels django.conf.settings.configure() à essayer de configurer certains paramètres. Par conséquent, si webapp.template est importé, avant tous les paramètres sont accessibles, alors settings.py n'est jamais chargé (comme les paramètres de l'accesseur constate qu'il existe déjà des paramètres, et ne pas essayer de charger plus).

La solution à cela est de forcer un accès aux paramètres, à la charge de l' settings.py, avant d' webapp.template est importé. Puis, quand webapp.template est ensuite importé, son appel à l' django.conf.settings.configure() est ignoré. J'ai donc changé le Django d'installation de version de code dans tous mes maîtres-chiens (et appengine_config.py) pour les opérations suivantes:

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' 

from google.appengine.dist import use_library
use_library('django', '1.2')

from django.conf import settings
_ = settings.TEMPLATE_DIRS

Dans la pratique, j'ai effectivement mis tout le code ci-dessus dans un fichier appelé" setup_django_version.py, puis les importer à partir de l'ensemble de mes gestionnaires, plutôt que de dupliquer ces 6 lignes de code partout.

J'ai ensuite mis à jour mon page_admin.html template à inclure ce (c'est à dire spécifier page_base.html par rapport à l' TEMPLATE_DIRS du réglage):

{% extends "page_base.html" %}

Et qui a résolu le problème avec le rendu de la page d'administration.

17voto

Dave W. Smith Points 9470

Depuis GAE 1.5.0, il existe un moyen beaucoup plus simple, bien que momentanément sous-documenté, de spécifier la version des modèles Django que vous souhaitez utiliser.

En appengine_config.py , incluez la ligne

 webapp_django_version = '1.2'
 

C'est tout.

Plus besoin de use_library() .

3voto

systempuntoout Points 27584

Selon la documentation que vous liez correctement, vous devriez simplement ajouter cette fonction au début de votre gestionnaire de script main.py .

2voto

Tyler Brandt Points 36

Une chose que je tiens à mentionner que la documentation n'est pas claire: si vous utilisez google.appengine.ext.deferred et ont use_library votre main.py, puis lorsque le report de la tâche est exécutée , il ne sera PAS chargé main.py et si vous êtes assez malheureux pour avoir un délai de tâche en tant que votre première demande à une instance, il bork l'instance (l'amenant à jeter UnacceptableVersionError quand votre main.py tente d'appeler use_library sur une demande ultérieure). Je pense que si vous ajoutez use_libary de appengine_config.py il collaborera avec l' deferred , mais nous avons fini par commutation de tâche périodique des files d'attente (les gestionnaires SONT acheminés par le biais main.py) pour éviter ce problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X