Как перезагрузить модуль модели 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 машины.

664   9  

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:

  1. внести изменения в модель (MyModel)
  2. удалить models.pyc
  3. очистить кэш модели 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
    
  4. обновить модель здесь

    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 не поддерживает запуск произвольного кода. Возможно, в будущем выпуске он имеет эту функцию.

Примечания:

  1. Django 1.10
  2. Python 3.4
  3. django_extension 1.7.4
  4. основанный (основной) на https://django-extensions.readthedocs.io/en/latest/shell_plus.html и http://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html
  5. осторожно. Это может привести к ошибке, если вы попытаетесь изменить код, где используется 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

  1. Установить IPython:pip install ipython
  2. выполнить python manage.py shell: символ в начале строки теперь должен быть In [1]: (в cmd это было >>>)
  3. выполнить ipython profile create
  4. поехать в ~/.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 модуль).

  1. создайте файл с именем 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) 
    
  2. Launch shell plus (который использует встроенный IPython оболочки):

    python manage.py shell_plus

  3. для импорта разрабатываемого модуля используйте следующее:

    %run local/reimport_module.py 'your.module'

  4. используйте IPython для тестирования функций в вашем модуле.

  5. внести изменения в модуль во внешнем редакторе.
  6. используйте следующее, чтобы повторно импортировать модуль без необходимости выхода и повторного входа в IPython:

    %run local/reimport_module.py 'your.module'

    Примечание: эта команда была уже использованы в шаге 3, так что вы можете типа %run затем стрелка вверх, чтобы автозаполнить его.

Comments

    Ничего не найдено.