web-dev-qa-db-fra.com

Comment recharger des modules dans le shell Django?

Je travaille avec Django et utilise Django Shell tout le temps. Le problème est que, bien que le serveur Django recharge les modifications de code, le shell ne le fait pas. Ainsi, chaque fois que je modifie une méthode que je teste, je dois quitter le shell et le redémarrer, puis réimporter tous les modules. besoin, réinitialisez toutes les variables dont j'ai besoin, etc. Tandis que l’historique iPython économise beaucoup de saisie à ce sujet, cela reste difficile. Existe-t-il un moyen de recharger automatiquement Django Shell, comme le serveur de développement Django?

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

68
Mad Wombat

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 là-bas dans une cellule, vos importations, etc. et exécutez-le. 

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

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

27
mpaf

regardez la commande manage.py Shell_plus fournie par le projet Django-extensions . Il chargera tous vos fichiers de modèle au démarrage de Shell. et autoreload votre tout modifier mais vous n'avez pas besoin de sortir, vous pouvez appeler directement

43
dongweiming

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

./manage.py Shell

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

Et à partir de maintenant, tous les modules importés seraient 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 commande %load_ext autoreload.

./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 à l'aide de la commande %aimport et de 3 stratégies de chargement automatique:

% auto-chargement

  • Recharger tous les modules (sauf ceux exclus par% aimport) automatiquement à présent. 

% auto-chargement 0

  • Désactiver le rechargement automatique. 

% auto-chargement 1

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

% autoreload 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 automatiquement importés ou ne pas l'être importé. 

% aimport foo

  • Importez le module ‘foo’ et marquez-le comme étant auto-chargé pour% auto-chargement 1

% aimport -foo

  • Marquez le module 'foo' pour ne pas le charger automatiquement.

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

  • Le remplacement des objets de code n'aboutit pas toujours: le remplacement d'une propriété @ dans une classe par une méthode ordinaire ou par une méthode par une variable membre peut poser problème (mais uniquement dans les anciens objets).
  • Les fonctions qui sont supprimées (par exemple via Monkey-Patching) d'un module avant son rechargement ne sont pas mises à niveau.
  • Les modules d'extension C ne peuvent pas être rechargés et ne peuvent donc pas être chargés automatiquement.
35
bodolsog

Il semble que le consensus général sur ce sujet est que python reload () est nul et il n’ya pas de bonne façon de le faire.

25
Mad Wombat

Ma solution consiste à écrire le code et à l'enregistrer dans un fichier, puis à utiliser:

python manage.py Shell <test.py

Ainsi, je peux apporter les modifications, enregistrer et réexécuter cette commande jusqu'à ce que je répare ce que j'essaie de réparer.

25
Erik

Reload () ne fonctionne pas dans Django Shell sans quelques astuces. Vous pouvez vérifier ce fil na et ma réponse spécifiquement:

Comment rechargez-vous un module de modèle Django à l'aide de l'interpréteur interactif via "manage.py Shell"?

4
Tomasz Zielinski

Ma solution à cet inconvénient est la suivante. 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)

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

À votre santé.

4
Roque

Au lieu d'exécuter des commandes depuis le shell Django, vous pouvez configurer une commande de gestion comme so et l'exécuter à chaque fois.

1
thomaspaulb

Utilisez Shell_plus avec un config ipython. Cela activera autoreload avant que Shell_plus n'importe automatiquement quoi que ce soit.

pip install Django-extensions
pip install ipython
ipython profile create

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

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

Ouvrez un shell - notez qu'il n'est pas nécessaire d'inclure --ipython:

python manage.py Shell_plus

Maintenant, tout ce qui est défini dans Shell_PLUS_PRE_IMPORTS ou Shell_PLUS_POST_IMPORTS ( docs ) sera automatiquement chargé!

0
andorov

Ce n’est pas exactement ce que vous voulez, mais j’ai maintenant tendance à me construire des commandes de gestion pour tester et manipuler des choses.

Dans la commande, vous pouvez configurer un groupe de locaux comme vous le souhaitez, puis les transférer 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 facile et moins ennuyeux de tester de manière interactive les fonctionnalités de Django.

0
toabi