Utilisateurs de Python et de Django, vous connaissez bien la commande :
./manage.py shell
qui permet de démarrer un shell Python dans l'environnement d'un projet Django en ayant connaissance de tous les paramètres de celui-ci. Vous pouvez alors faire sans difficulté :
>>>> from projet.application import models
sans vous faire insulter sous prétexte que le chemin de votre projet n'est pas dans sys.path.
Si vous utilisez IPython, vous bénéficiez alors de tous les avantages de cet environnement de travail. Toutefois, si vous travaillez avec le shell standard, vous avez remarqué que cette façon de le démarrer n'honore pas la variable PYTHONSTARTUP. Donc votre ~/.pythonstartup.py aux petits oignons qui vous apportait le support bienvenu de la readline avec la complétion automatique et l'historique [1], il n'est pas lu. Pas d'historique, pas de gadgets pratiques, les yeux pour pleurer, point.
Des solutions sont proposées sur le trac de Django :
Toutefois elles n'ont pas été intégrées au trunk. Ça ne m'étonne que moyennement, je les ai essayées sans succès. Je pense que ça n'est pas grand chose, mais je n'avais pas le temps de creuser ce jour là.
Et je me suis demandé si on ne pouvait pas faire les choses dans l'autre sens : au lieu de bricoler Django pour lui faire lire le fichier de startup, pourquoi ne pas bricoler le fichier de startup pour lui faire intégrer d'éventuels paramètres de Django ? Et plus généralement, pourquoi ne pas lui faire intégrer d'éventuels paramètres propres à n'importe quel projet ?
En fait, ce n'est pas original, puisque la documentation de Python elle-même évoque cette solution (dans le tutorial). Faites-donc cette modification à votre fichier de startup. Reste à créer un fichier .pythonrc.py qui permette d'intégrer l'environnement nécessaire. Je me suis fortement inspiré de la fonction setup_environ dans le fichier django/core/management. Celle-ci est idéale pour le code d'un programme python situé à la racine de votre projet :
#!/usr/bin/python from django.core.management import setup_environ import settings setup_environ(settings)
Cependant cette solution ne fonctionne pas telle quelle dans le cadre d'un lancement de shell. J'ai donc adapté le code de la fonction, en particulier pour que le chemin du projet soit correctement reconnu.
Tout d'abord, ajoutez à votre settings.py :
import os.path PROJECT_PATH = os.path.dirname(os.path.abspath(__file__))
(Je crois que j'ai piqué ce truc à David de BioloGeek). Cela vous servira probablement ailleurs, y compris dans settings.py lui-même, pour rendre votre code plus portable en faisant des choses comme :
TEMPLATE_DIRS = (os.path.join(PROJECT_PATH, 'templates'),)
Mais je m'égare. Donc, renseignez correctement la variable PROJECT_PATH, puis créez le fichier .pythonrc.py suivant à la racine de votre projet :
#!/usr/bin/python
import os,sys
try:
import settings
except ImportError:
print "Unable to import settings."
sys.exit(1)
# Sets project path in modules search path
project_name = os.path.basename(settings.PROJECT_PATH)
settings_name = os.path.splitext(settings.__file__)[0]
sys.path.append(os.path.join(settings.PROJECT_PATH, '..'))
project_module = __import__(project_name, {}, {}, [''])
sys.path.pop()
# Set DJANGO_SETTINGS_MODULE appropriately.
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
print "Django environment of project %s registered." % os.environ['DJANGO_SETTINGS_MODULE']
Il ne vous reste plus qu'à admirer...:
[11:34][anhj@shound ~/path/to/myproject]$ python Python 2.4.4 (#2, Jul 21 2007, 11:00:24) [GCC 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)] on linux2 Type "help", "copyright", "credits" or "license" for more information. Current history file (/home/anhj/.py_history) size: 7087 bytes, 339 lines. Django environment of project myproject.settings registered. >>>
Bon, excusez-moi, je retourne faire des trucs.
| [1] | Voir par exemple http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/473900 |
A Django site.