Django kabuğundaki modüller nasıl yeniden yüklenir?


92

Django ile çalışıyorum ve her zaman Django kabuğu kullanıyorum. Can sıkıcı kısım, Django sunucusu kod değişikliklerini yeniden yüklerken kabuğun bunu yapmamasıdır, bu yüzden test ettiğim bir yöntemde her değişiklik yaptığımda, kabuktan çıkıp yeniden başlatmam, tüm modülleri yeniden içe aktarmam gerekir. ihtiyacım var, ihtiyacım olan tüm değişkenleri yeniden başlat, vb. iPython geçmişi bu konuda çok fazla yazım tasarrufu sağlasa da, bu hala bir acı. Django geliştirme sunucusunun yaptığı gibi django kabuğunu otomatik yeniden yüklemenin bir yolu var mı?

Reload () hakkında bilgim var, ancak birçok modeli içe aktarıyorum ve genellikle from app.models import *sözdizimi kullanıyorum, bu nedenle reload () pek yardımcı olmuyor.


2
"Django-extensions" yanıtını doğru olarak işaretlemek için bu soruyu güncellemelisiniz.
woodardj

1
Benim için gerçekten işe yarayana kadar olmaz. Uzantıları yükledim ve kodumun hiçbiri otomatik olarak yeniden yüklenmiyor ve shell_plus belgelerinde otomatik yeniden yüklemeden bahsetmiyor. Runserver_plus komutunda bir yeniden yükleyici var gibi görünüyor, ama aradığım bu değil.
Mad Wombat

Yanıtlar:


38

Yukarıda dongweiming tarafından belirtildiği gibi django-extension projesini kullanmanızı tavsiye ederim. Ancak sadece 'shell_plus' yönetim komutu yerine şunu kullanın:

manage.py shell_plus --notebook

Bu, web tarayıcınızda bir IPython not defteri açacaktır. Kodunuzu oraya bir hücreye yazın, içe aktarmalarınızı vb. Yazın ve çalıştırın.

Modüllerinizi değiştirdiğinizde, sadece 'Kernel-> Restart' not defteri menü öğesini tıklayın.

İşte böyle, kodunuz artık değiştirilmiş modüllerinizi kullanıyor.


32
"Sadece bir python not defteri kullanın", OP'nin sorusuna bir cevap değildir.
J__

1
Bu yöntem,% autoreload gibi otomatik olmasa da, otomatik yeniden yüklemeden daha güvenilir çalışır. Çekirdek yeniden başlatma, dizüstü bilgisayardaki tüm hücrelerin modüllerin tamamen yeniden yüklenmesini garanti eder. Ayrıca isterseniz tüm hücreleri yeniden başlatabilir ve çalıştırabilirsiniz.
Anton I. Sipos

76

IPython otomatik yeniden yükleme uzantısını kullanmanızı öneririm .

./manage.py shell

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

Ve şu andan itibaren, içe aktarılan tüm modüller değerlendirilmeden önce yenilenecektir.

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'

Komuttan önce bir şey içe aktarılmışsa da çalışır %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'

Bazı içe %aimportaktarmaların komut ve 3 otomatik yeniden yükleme stratejisi ile yenilenmesini engellemek de mümkündür :

% otomatik yeniden yükleme

  • Tüm modülleri (% aimport tarafından hariç tutulanlar hariç) şimdi otomatik olarak yeniden yükle.

% otomatik yeniden yükleme 0

  • Otomatik yeniden yüklemeyi devre dışı bırakın.

% autoreload 1

  • Yazılan Python kodunu çalıştırmadan önce her seferinde% aimport ile içe aktarılan tüm modülleri yeniden yükleyin.

% autoreload 2

  • Yazılan Python kodunu çalıştırmadan önce tüm modülleri (% aimport tarafından hariç tutulanlar hariç) her seferinde yeniden yükleyin.

% aimport

  • Otomatik olarak içe aktarılacak veya alınmayacak modülleri listeleyin.

% aimport foo

  • 'Foo' modülünü içe aktarın ve% autoreload 1 için otomatik olarak yeniden yüklenecek şekilde işaretleyin

% aimport -foo

  • Modül 'foo' otomatik olarak yüklenmeyecek şekilde işaretleyin.

Bu genellikle benim kullanımım için iyi çalışıyor, ancak bazı boşluklar var:

  • Kod nesnelerini değiştirmek her zaman başarılı olmaz: Bir sınıftaki @ özelliğini sıradan bir yönteme veya bir yöntemi üye değişkenine dönüştürmek sorunlara neden olabilir (ancak yalnızca eski nesnelerde).
  • Yeniden yüklenmeden önce bir modülden kaldırılan işlevler (örn. Maymun yaması yoluyla) yükseltilmez.
  • C genişletme modülleri yeniden yüklenemez ve bu nedenle otomatik olarak yeniden yüklenemez.

3
Django'yu kullanıyorsanız /manage.py shell_plus... yazarsanız %load_ext autoreloadve sonra %autoreload 2modeller otomatik olarak yeniden yüklenir.
Fusion


Açıkçası bunun için ipython'a ihtiyacınız olduğunu unutmayın. Örneğin stackoverflow.com/a/47170195/50899
Rabarberski

bu% otomatik yeniden yükleme nereye koyulur? Cevap net değil
IceFire

40

Çözümüm, kodu yazıp bir dosyaya kaydettikten sonra şunu kullanmaktır:

python manage.py kabuk <test.py

Böylece, düzeltmeye çalıştığım şeyi düzeltene kadar değişikliği yapabilir, kaydedebilir ve bu komutu tekrar çalıştırabilirim.


2
Güzel ve basit. Bir not, exit()Django kabuğundan daha temiz bir şekilde çıkmak için py dosyasının altına ekleyin . Teşekkür.
Marc

Basit ve zarif çözüm. Aferin.
nikoskip

38

django-extensions projesi tarafından sağlanan manage.py shell_plus komutuna bakın . Tüm model dosyalarınızı kabuk başlangıcında yükleyecektir. ve herhangi bir değişikliğinizi otomatik olarak yeniden yükleyin, ancak çıkış yapmanız gerekmiyorsa, oraya yönlendirebilirsiniz


41
Shell_plus kullanıyorum ve modellerim otomatik olarak yeniden yüklenmiyor, eksik bir şey mi var?
Diego Ponciano

31
shell_plus modelleri yeniden yüklemiyor, bu yüzden bu soruya cevap vermiyor.
aljabear

5
söylendiği gibi, shell_plus modelleri yeniden yüklemiyor.
zenperttu

2
Belki bir şeyi kaçırıyorum ama shell_plus benim için hiçbir şeyi yeniden yüklemiyor. Tüm modelleri başlangıçta yükler, bu da uygundur, ancak budur.
Mad Wombat

14
shell_plus, otomatik yeniden yükleme modülünü kullanarak modülleri yeniden yükleyebilir. '% Load_ext autoreload' ve ardından '% autoreload 2' yazın - bkz. İpython.org/ipython
doc/3/

25

Görünüşe göre bu konudaki genel fikir birliği, python reload () 'un berbat olduğu ve bunu yapmanın iyi bir yolu olmadığıdır.


Yanlış. @ dongweiming'in yukarıdaki cevabı çözümdür ve en iyi cevap olarak kabul edilmelidir.
Joseph Sheedy

3
Yanıtıyla ilgili birçok yorum, shell_plus'ın modelleri yeniden yüklemediğini söylüyor
Mad Wombat

1
Kendim test ettim ve yeniden yüklenmiyor. Ayrıca, elle içe aktardığım model dışı kod ne olacak?
Mad Wombat

Kullanmakta olduğum bir uygulamadaki sınıflar, düz bir django olmayan model modülü ve içindeki sınıf dahil olmak üzere artık harika (Python 3.4.3, Django 1.9b1, django-uzantıları 1.5.9) yeniden yükleniyor. Bu cevabın üzerinden 5 yıl geçti ve pek çok gelişme oldu.
Joseph Sheedy

1
40 dakika önce kurulumumda denedim ve shell_plus benim için hiçbir şey yüklemiyor. Django 1.7.10, python 3.4.3, django-uzantıları 1.5.9.
Mad Wombat

6

Bu uygunsuzluk için benim çözümüm aşağıda. IPython kullanıyorum.

$ ./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)

İçin Python 3.x , 'yeniden' kullanılarak aktarılması gerekir:

from importlib import reload

Umarım yardımcı olur. Elbette hata ayıklama amaçlıdır.

Şerefe.



4

Shell_plus'ı bir ipython yapılandırmasıyla kullanın . Bu, autoreloadshell_plus herhangi bir şeyi otomatik olarak içe aktarmadan önce etkinleştirilecektir .

pip install django-extensions
pip install ipython
ipython profile create

İpython profilinizi düzenleyin ( ~/.ipython/profile_default/ipython_config.py):

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

Bir kabuk açın - şunları eklemenize gerek olmadığını unutmayın --ipython:

python manage.py shell_plus

Şimdi SHELL_PLUS_PRE_IMPORTSveya SHELL_PLUS_POST_IMPORTS( docs ) içinde tanımlanan herhangi bir şey otomatik olarak yeniden yüklenecek!

pdb.set_trace()Bir dosyayı kaydettiğinizde kabuğunuz bir hata ayıklayıcıdaysa (örn. ), Yeniden yüklemeyi engelleyebileceğini unutmayın.


2
Cevap için teşekkür ederim. Yine de 2010'da sorduğumu fark edebilirsiniz. Sekiz yıl sonra otomatik yeniden yüklemenin nihayet shell_plus'ta çalıştığını bilmekten memnunum :)
Mad Wombat

1

Bunun yerine Django kabuğundan komutların çalışması, bir yönetim komutu kurabilirsiniz şöyle ve yeniden çalıştırın her zaman yapacak.


1

Bunun için 2 cevabın bir kombinasyonunu kullanarak basit bir tek satırlık yaklaşım buldum.

Django kabuğunu -c ile çalıştırabilirsiniz, bu da ilettiğiniz komutları çalıştırır, ancak kod çalıştırıldıktan hemen sonra kapanır .

İşin püf noktası, ihtiyacınız olanı kurmak, code.interact (local = locals ()) komutunu çalıştırmak ve ardından geçtiğiniz kodun içinden kabuğu yeniden başlatmaktır. Bunun gibi:

python manage.py shell -c 'import uuid;test="mytestvar";import code;code.interact(local=locals())'

Benim için sadece zengin kütüphanenin inceleme yöntemini istedim. Yalnızca birkaç satır:

python manage.py shell -c 'import code;from rich import pretty;pretty.install();from rich import inspect;code.interact(local=locals())'

Sonunda üstteki kiraz bir takma addır

alias djshell='python manage.py shell -c "import code;from rich import pretty;pretty.install();from rich import inspect;code.interact(local=locals())"'

Şimdi, kabuğumu başlatırsam ve ders sınıfını incelemek istersem, bu güzel çıktıyı elde ederim: görüntü açıklamasını buraya girin


0

Tam olarak istediğiniz şey değil, ama şimdi kendimi test etmek ve bazı şeylerle uğraşmak için yönetim komutları oluşturma eğilimindeyim.

Komutta, istediğiniz şekilde bir grup yerel ayarlayabilir ve ardından etkileşimli bir kabuğa düşebilirsiniz.

import code

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

Yeniden yükleme yok, ancak django işlevselliğini etkileşimli olarak test etmenin kolay ve daha az sinir bozucu bir yolu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.