Как перезагрузить модуль модели Django с помощью интерактивного интерпретатора через "manage.py Шелл"?
Я знаю, как перезагрузить обычный модуль Python в обычном сеансе интерпретатора Python. Этот вопрос, как это сделать очень хорошо:
как выгрузить (перезагрузить) модуль Python?
по какой-то причине у меня возникли проблемы с этим в Джанго "manage.py shell" сеанс интерпретатора. Чтобы воссоздать мою проблему, запустите базовый учебник Django, найденный здесь:
написание вашего первого приложения Django, часть 1
после создания приложения "опросы" и класса "опрос" запустите интерпретатор через "manage.py оболочка "и импортировать приложение" опросы " в него.
import polls.models as pm
создать новый объект "опрос":
p = pm.Poll()
все хорошо и хорошо до сих пор. Теперь вернитесь к источнику и добавьте любой произвольный метод или атрибут. Например, я добавил:
def x(self):
return 2+2
теперь вернитесь к интерпретатору и" перезагрузите " модуль:
reload(pm)
теперь попробуйте использовать ваш новый метод или атрибут:
p1 = pm.Poll()
p1.x()
вы получили это сообщение:
'Poll' object has no attribute 'x'
что это дает? Я также попытался перезапустить команду импорта, импортируя модуль с использованием другого синтаксиса, удаляя все ссылки на любые объекты "опроса" или на класс "опрос". Я также попытался это с оболочкой IPython переводчика и с обычного на языке Python (версии 2.6) переводчик. Кажется, ничего не работает.
используя те же методы с произвольным модулем Python в обычном сеанс интерпретатора работает отлично. Я просто не могу заставить его работать в сеансе "оболочки" Django.
кстати, если это имеет какое-то значение, я делаю это на Ubuntu 9.04 машины.
9 ответов:
Ну, я думаю, я должен ответить на это. Проблема в том, что Django кэширует свои модели в одноэлементной (одноэлементной структуре), называемой AppCache. В принципе, для перезагрузки моделей Django вам нужно сначала перезагрузить и повторно импортировать все модули модели, хранящиеся в AppCache. Затем вам нужно уничтожить AppCache. Вот ее код:
import os from django.db.models.loading import AppCache cache = AppCache() curdir = os.getcwd() for app in cache.get_apps(): f = app.__file__ if f.startswith(curdir) and f.endswith('.pyc'): os.remove(f) __import__(app.__name__) reload(app) from django.utils.datastructures import SortedDict cache.app_store = SortedDict() cache.app_models = SortedDict() cache.app_errors = {} cache.handled = {} cache.loaded = FalseЯ поместил все это в отдельный файл под названием reloadmodels.py в корневом каталоге моего сайта Django. С помощью IPython я могу перезагрузить все работает:
%run ~/mysite/reloadmodels.py
вы также можете использовать проект django-extensions со следующей командой:
manage.py shell_plus --notebookэто откроет ноутбук IPython в вашем веб-браузере вместо интерпретатора оболочки IPython. Напишите там свой код и запустите его.
когда вы меняете свои модули, просто нажмите на пункт меню веб-страницы "ядро - > перезагрузка"
повторный запуск кода теперь использует измененные модули.
Предположим ваш проект настроен таким образом
- название проекта : Книжный магазин
- имя приложения : полка
- название модели : книги
загрузить
from bookstore.shelf.models import Booksпоследующих перезагрузок
import bookstore;reload(bookstore.shelf.models);from bookstore.shelf.models import Books
насколько я понимаю, ни одно из вышеперечисленных решений не работало самостоятельно, также этой поток сам по себе не очень помог, но после объединения подходов мне удалось перезагрузить мои модели в shell_plus:
- внести изменения в модель (MyModel)
- удалить
models.pycочистить кэш модели Django (например здесь):
from django.db.models.loading import AppCache cache = AppCache() from django.utils.datastructures import SortedDict cache.app_store = SortedDict() cache.app_models = SortedDict() cache.app_errors = {} cache.handled = {} cache.loaded = Falseобновить модель здесь
reload(project.app.models) from project.app.models import MyModel
IPython console тут глубокая перезагрузка С каждого
reload()выражение; и, конечно, добавляет множество других полезных вещей.
мое решение на 2016 год (в будущем оно может быть изменено)
1.Установите django_extension
2.Добавить следующие настройки:
SHELL_PLUS = 'ipython' IPYTHON_ARGUMENTS = [ '--ext', 'autoreload', ]3.Запустить оболочку
./manage.py shell_plusпосмотреть результаты:
модель например
class Notification(models.Model): ........ @classmethod def get_something(self): return 'I am programmer'в корпус
In [1]: Notification.get_something() Out[1]: 'I am programmer'внесены изменения в модель
@classmethod def get_something(self): return 'I am Python programmer'в корпус
# shell does not display changes In [2]: Notification.get_something() Out[2]: 'I am programmer'в Shell. Это магия
# configure extension of ipython In [3]: %autoreload 2в корпус
# try again - all worked In [4]: Notification.get_something() Out[4]: 'I am Python programmer'снова изменения
@classmethod def get_something(self): return 'I am full-stack Python programmer'в корпус
# all worked again In [5]: Notification.get_something() Out[5]: 'I am full-stack Python programmer'недостаток: 1. Нужно вручную запустить код
%autoreload 2
так как django_extension 1.7 не поддерживает запуск произвольного кода. Возможно, в будущем выпуске он имеет эту функцию.
Примечания:
- Django 1.10
- Python 3.4
- django_extension 1.7.4
- основанный (основной) на https://django-extensions.readthedocs.io/en/latest/shell_plus.html и http://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html
- осторожно. Это может привести к ошибке, если вы попытаетесь изменить код, где используется super().
включить оболочкой IPython расширение автоматическая перезагрузка перед импортом код:
%load_ext autoreload %autoreload 2Я использую его с обычной оболочкой django, и он отлично работает, хотя у него есть некоторые ограничения:
*предостережения:
перезагрузка модулей Python надежным способом в целом затруднена, и могут произойти неожиданные вещи. %autoreload пытается обойти общие подводные камни, заменяя объекты кода функции и части классов ранее в модуле с помощью новая версия. Это делает следующие вещи, чтобы работать:
- функции и классы, импортированные через "from xxx import foo", обновляются до новых версий при перезагрузке "xxx".
- методы и свойства классов обновляются при перезагрузке, так что вызов ‘c.foo()’ на объекте ‘c’, созданном до перезагрузки, вызывает выполнение нового кода для ‘foo’.
некоторые из известных оставшихся предостережений являются:
- замена кода объекты не всегда преуспевают: изменение свойства @в классе на обычный метод или метод на переменную-член может вызвать проблемы (но только в старых объектах).
- функции, которые будут удалены (напр. через monkey-patching) из модуля до его перезагрузки не обновляются.
- модули расширения C не могут быть перезагружены и поэтому не могут быть загружены автоматически.*
источник: https://ipython.org/ipython-doc/3/config/extensions/autoreload.html#caveats
еще один отличный вариант-написать свой код в отдельном скрипте и отправить его в оболочку django, например:
manage.py shell < my_script.py
из ответов Seti Volkylany и pv
- Установить IPython:
pip install ipython- выполнить
python manage.py shell: символ в начале строки теперь должен бытьIn [1]:(в cmd это было>>>)- выполнить
ipython profile createпоехать в
~/.ipython/profile_default/ipython_config.pyи откройте его в текстовом редакторе и добавьте следующие две строки в конце:Си.InteractiveShellApp.выдвижений= ['автоматическая перезагрузка']
c. InteractiveShellApp.exec_lines = ['%autoreload 2']теперь вы можете запустить
python manage.py shell, редактировать модели без необходимости писать%autoreload 2
Я не смог получить ни одно из вышеперечисленных решений для работы, но я придумал обходной путь для перезагрузки любого другого модуля без моделей в моем проекте django (например, a
functions.pyилиviews.pyмодуль).
создайте файл с именем
reimport_module.py. Я хранил его вlocal/папка моего проекта django на моей машине dev.# Desc: Imports the module with the name passed in, or imports it for first # time if it hasn't already been imported. # # Purpose of this script is to speed up development of functions that # are written in an external editor then tested in IPython. # # Without this script you have to exit & reenter IPython then redo # import statements, definitions of local variables, etc. # # Note: doesn't work for Django models files, because Django caches # them in a structure called AppCache. # # Args: module to reload (string) import sys module_to_reload = sys.argv[1] # Attempt to pop module try: sys.modules.pop(module_to_reload) print 'reimporting...' except KeyError: print 'importing for first time...' # (re)import module import_str = 'from {0} import *'.format(module_to_reload) exec(import_str)Launch shell plus (который использует встроенный IPython оболочки):
python manage.py shell_plusдля импорта разрабатываемого модуля используйте следующее:
%run local/reimport_module.py 'your.module'используйте IPython для тестирования функций в вашем модуле.
- внести изменения в модуль во внешнем редакторе.
используйте следующее, чтобы повторно импортировать модуль без необходимости выхода и повторного входа в IPython:
%run local/reimport_module.py 'your.module'Примечание: эта команда была уже использованы в шаге 3, так что вы можете типа
%runзатем стрелка вверх, чтобы автозаполнить его.
Comments