Comment recharger des modules dans le shell django?

90

Je travaille avec Django et j'utilise le shell Django tout le temps. La partie ennuyeuse est que tandis que le serveur Django se recharge sur les changements de code, le shell ne le fait pas, donc chaque fois que je modifie une méthode que je teste, je dois quitter le shell et le redémarrer, réimporter tous les modules que je besoin, réinitialisez toutes les variables dont j'ai besoin, etc. Alors que l'historique d'iPython économise beaucoup de saisie à ce sujet, c'est toujours une douleur. Existe-t-il un moyen de recharger automatiquement le shell django, de la même manière que le serveur de développement django?

Je connais reload (), mais j'importe beaucoup de modèles et j'utilise généralement la from app.models import *syntaxe, donc reload () n'aide pas beaucoup.

Wombat fou
la source
2
Vous devriez mettre à jour cette question pour marquer la réponse "django-extensions" comme correcte.
woodardj
1
Pas avant que ça marche pour moi. J'ai les extensions installées et aucun de mes codes ne se recharge automatiquement et je ne vois aucune mention de rechargement automatique dans la documentation shell_plus. Il semble qu'il y ait un rechargement dans la commande runserver_plus, mais ce n'est pas ce que je recherche.
Mad Wombat

Réponses:

37

Je recommande d'utiliser le projet django-extensions comme indiqué ci-dessus par dongweiming. Mais au lieu de simplement la commande de gestion 'shell_plus', utilisez:

manage.py shell_plus --notebook

Cela ouvrira un bloc-notes IPython sur votre navigateur Web. Écrivez votre code dans une cellule, vos importations etc. et exécutez-le.

Lorsque vous modifiez vos modules, cliquez simplement sur l'élément de menu du notebook 'Kernel-> Restart'

Voilà, votre code utilise maintenant vos modules modifiés.

mpaf
la source
30
"Il suffit d'utiliser un cahier python" n'est pas une réponse à la question du PO.
J__
Cette méthode, bien que n'étant pas automatique comme% autoreload, fonctionne de manière plus fiable que la recharge automatique. Le redémarrage du noyau garantit que toutes les cellules du notebook reçoivent des modules entièrement rechargés. De plus, vous pouvez redémarrer et exécuter toutes les cellules si vous le souhaitez.
Anton I. Sipos
72

Je suggère d'utiliser l' extension de chargement automatique IPython .

./manage.py shell

In [1]: %load_ext autoreload
In [2]: %autoreload 2

Et à partir de maintenant, tous les modules importés seront actualisés avant d'être évalués.

In [3]: from x import print_something
In [4]: print_something()
Out[4]: 'Something'

 # Do changes in print_something method in x.py file.

In [5]: print_something()
Out[5]: 'Something else'

Fonctionne également si quelque chose a été importé avant la %load_ext autoreloadcommande.

./manage.py shell
In [1]: from x import print_something
In [2]: print_something()
Out[2]: 'Something'

 # Do changes in print_something method in x.py file.

In [3]: %load_ext autoreload
In [4]: %autoreload 2
In [5]: print_something()
Out[5]: 'Something else'

Il est également possible d'empêcher l'actualisation de certaines importations avec la %aimportcommande et 3 stratégies de chargement automatique:

% chargement automatique

  • Rechargez tous les modules (sauf ceux exclus par% aimport) automatiquement maintenant.

% chargement automatique 0

  • Désactivez le rechargement automatique.

% chargement automatique 1

  • Rechargez tous les modules importés avec% aimport à chaque fois avant d'exécuter le code Python tapé.

% chargement automatique 2

  • Rechargez tous les modules (sauf ceux exclus par% aimport) à chaque fois avant d'exécuter le code Python tapé.

% aimport

  • Liste des modules qui doivent être importés automatiquement ou non.

% aimport foo

  • Importez le module 'foo' et marquez-le comme étant chargé automatiquement pour% autoreload 1

% aimport -foo

  • Marquer le module «foo» pour ne pas être chargé automatiquement.

Cela fonctionne généralement bien pour mon utilisation, mais il y a quelques cavetas:

  • Le remplacement des objets de code ne réussit pas toujours: changer une propriété @ dans une classe en une méthode ordinaire ou une méthode en une variable membre peut poser des problèmes (mais dans les anciens objets uniquement).
  • Les fonctions supprimées (par exemple via monkey-patching) d'un module avant qu'il ne soit rechargé ne sont pas mises à jour.
  • Les modules d'extension C ne peuvent pas être rechargés et ne peuvent donc pas être rechargés automatiquement.
Bodolsog
la source
3
Si vous utilisez django's /manage.py shell_plus... si vous tapez %load_ext autoreloadet ensuite %autoreload 2, les modèles seront automatiquement rechargés.
Fusion
Incroyable, tu as fait ma journée
Shamsul Arefin Sajib
Notez que vous avez évidemment besoin d'installer ipython pour cela. Voir par exemple stackoverflow.com/a/47170195/50899
Rabarberski
38

regardez la commande manage.py shell_plus fournie par le projet django-extensions . Il chargera tous vos fichiers de modèle au démarrage du shell. et rechargez automatiquement vos modifications mais n'avez pas besoin de quitter, vous pouvez y appeler directement

Dongweiming
la source
40
J'utilise shell_plus et mes modèles ne se rechargent pas automatiquement, est-ce que je manque quelque chose?
Diego Ponciano
30
shell_plus ne recharge pas les modèles, donc cela ne répond pas à la question.
aljabear le
5
comme dit, shell_plus ne recharge pas les modèles.
zenperttu
2
Il me manque peut-être quelque chose, mais shell_plus ne recharge rien pour moi. Il charge tous les modèles au démarrage, ce qui est pratique, mais c'est tout.
Mad Wombat
14
shell_plus peut recharger les modules à l'aide du module de recharge automatique. Tapez '% load_ext autoreload' puis '% autoreload 2' - voir ipython.org/ipython-doc/3/config/extensions/autoreload.html
bbrame
37

Ma solution est d'écrire le code et d'enregistrer dans un fichier, puis d'utiliser:

shell python manage.py <test.py

Je peux donc effectuer le changement, enregistrer et exécuter à nouveau cette commande jusqu'à ce que je répare tout ce que j'essaie de réparer.

Erik
la source
2
Sympa et simple. Une note, ajoutez exit()au bas du fichier py pour quitter le shell Django de manière plus propre. Merci.
Marc
Solution simple et élégante. Bon travail.
nikoskip le
25

Il semble que le consensus général sur ce sujet soit que python reload () est nul et qu'il n'y a pas de bon moyen de le faire.

Wombat fou
la source
Incorrect. La réponse de @ dongweiming ci-dessus est la solution et devrait être acceptée comme la meilleure réponse.
Joseph Sheedy
3
Plusieurs commentaires sur sa réponse disent que shell_plus ne recharge pas les modèles
Mad Wombat
1
Je viens de le tester moi-même et il ne se recharge pas. D'ailleurs, qu'en est-il du code non-modèle que j'importe à la main?
Mad Wombat
Les classes dans une application que j'utilise maintenant se rechargent très bien (Python 3.4.3, Django 1.9b1, django-extensions 1.5.9), y compris un module non-modèle de django et la classe qu'il contient. Cela fait 5 ans depuis cette réponse, et beaucoup de développement s'est produit.
Joseph Sheedy
1
Je l'ai essayé sur ma configuration il y a 40 minutes et shell_plus ne recharge rien pour moi. Django 1.7.10, python 3.4.3, django-extensions 1.5.9.
Mad Wombat
5

Ma solution à cet inconvénient suit. J'utilise IPython.

$ ./manage.py shell
> import myapp.models as mdls   # 'mdls' or whatever you want, but short...
> mdls.SomeModel.objects.get(pk=100)
> # At this point save some changes in the model
> reload(mdls)
> mdls.SomeModel.objects.get(pk=100)

Pour Python 3.x , 'reload' doit être importé en utilisant:

from importlib import reload

J'espère que cela aide. Bien sûr, c'est à des fins de débogage.

À votre santé.

Roque
la source
2

Utilisez shell_plus avec une configuration ipython. Cela autoreloadactivera avant que shell_plus importe automatiquement quoi que ce soit.

pip install django-extensions
pip install ipython
ipython profile create

Modifiez votre profil ipython ( ~/.ipython/profile_default/ipython_config.py):

c.InteractiveShellApp.exec_lines = ['%autoreload 2']
c.InteractiveShellApp.extensions = ['autoreload']

Ouvrez un shell - notez que vous n'avez pas besoin d'inclure --ipython:

python manage.py shell_plus

Désormais, tout ce qui est défini dans SHELL_PLUS_PRE_IMPORTSou SHELL_PLUS_POST_IMPORTS( docs ) se recharge automatiquement!

Notez que si votre shell est au niveau d'un débogueur (ex pdb.set_trace()) lorsque vous enregistrez un fichier, cela peut interférer avec le rechargement.

Andorov
la source
1
Merci pour la réponse. Vous noterez peut-être que je l'ai posé en 2010. Je suis heureux de savoir qu'après huit ans le rechargement automatique fonctionne enfin dans shell_plus :)
Mad Wombat
1

Au lieu d'exécuter des commandes depuis le shell Django, vous pouvez configurer une commande de gestion comme celle-ci et la réexécuter à chaque fois.

petit vert
la source
0

Pas exactement ce que vous voulez, mais j'ai maintenant tendance à me créer des commandes de gestion pour tester et manipuler les choses.

Dans la commande, vous pouvez configurer un groupe de locaux comme vous le souhaitez et ensuite les déposer dans un shell interactif.

import code

class Command(BaseCommand):
  def handle(self, *args, **kwargs):
     foo = 'bar'
     code.interact(local=locals())

Pas de rechargement, mais un moyen simple et moins ennuyeux de tester interactivement les fonctionnalités de django.

toabi
la source