Как заставить мой Django manage.py работать правильно, когда к файлам обращаются через символическую ссылку? - PullRequest
4 голосов
/ 04 мая 2011

Проблема

При попытке выполнить одну из моих пользовательских команд управления Django (send_notify_emails) я получаю следующую ошибку:

$ python web_apps/manage.py send_notify_emails
Traceback (most recent call last):
  File "web_apps/manage.py", line 11, in <module>
    execute_manager(settings)
  File "/usr/lib/python2.7/site-packages/django/core/management/__init__.py", line 436, in execute_manager
    setup_environ(settings_mod)
  File "/usr/lib/python2.7/site-packages/django/core/management/__init__.py", line 419, in setup_environ
    project_module = import_module(project_name)
  File "/usr/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
ImportError: No module named my_django_app-1.0

Фон

У меня есть сайт Django с двумя приложениями.Путь к каталогу сайта (который включает в себя каталоги модулей приложения, а также settings.py, urls.py и manage.py) составляет /srv/web_apps.Это символическая ссылка на /usr/share/my_django_app-1.0, которая является svn export тега выпуска продукта.Таким образом, я могу изменить версию своего приложения, просто переместив символическую ссылку на путь для новой рабочей версии, и, при необходимости, легко вернуться к более раннему выпуску.

Мой django.wsgi файл добавляет /srv и /srv/web_apps к пути Python, чтобы mod_wsgi мог найти мои настройки и файлы url, а также модули приложения.

ЕДИНСТВЕННОЕ место, где появляется my_django_app-1.0, это путь к каталогу, онего нет нигде в моем settings.py или где-либо еще, поэтому Django должен получать имя модуля по пути.

То, что , по-видимому, происходит, - Django разрешает имя пакета для моего приложения.следуя по символической ссылке и используя имя целевой папки, вместо самой символической ссылки.Когда я запускаю manage.py, Django пытается импортировать my_django_app-1.0, когда он должен импортировать web_apps.

1 Ответ

3 голосов
/ 15 февраля 2012

У меня есть сайт Django с двумя приложениями. Путь к сайту каталог (который включает в себя каталоги модуля приложения, а также settings.py, urls.py и manage.py) - это / srv / web_apps. Это символическая ссылка на /usr/share/my_django_app-1.0, которая является экспортом SVN тега выпуска продукции. Таким образом, я могу изменить версию своего приложения просто переместив символическую ссылку на путь для нового производства версии, и при необходимости легко вернитесь к более раннему выпуску.

То, что вы описываете, является в основном точной причиной, по которой людям так нравится virtualenv. Я бы посоветовал прочитать mod_wsgi Виртуальные среды .

Проблема в том, что __file__ возвращает символическую ссылку относительный путь, который в зависимости от о том, откуда он импортируется (внутри пути символической ссылки ..), вот как он будет сообщать это дом Поскольку каталоги являются базовой структурой модулей, если у вас есть каталог с __init__.py в нем, то, что бы ни назвали в этом каталоге, будет ' name ' если вы импортируете это.

Возможно, вы сможете изменить это поведение, но это был бы неправильный путь вещи - проверьте virtualenv, или установите отдельные каталоги для каждой версии и просто используйте подчеркивает вместо периодов. myApp_1_0_0 и т. Д.

Рассмотрим следующий сценарий

mkdir real_directory
ln -s real_directory symlink_directory
cat >>real_directory/__init__.py <<EOF
import os
print
print '__name__ == %s' % (__name__)
print '__file__ == %s' % (__file__)
print ' abspath == %s' % os.path.abspath(__file__)
print 'realpath == %s' % os.path.realpath(os.path.abspath(__file__))
print
EOF

python -c "import real_directory"

__name__ == real_directory
__file__ == real_directory/__init__.py
 abspath == /Users/nar/pt/real_directory/__init__.py
realpath == /Users/nar/pt/real_directory/__init__.py

python -c "import symlink_directory"

__name__ == symlink_directory
__file__ == symlink_directory/__init__.pyc
 abspath == /Users/nar/pt/symlink_directory/__init__.pyc
realpath == /Users/nar/pt/real_directory/__init__.pyc
...