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

#python #django #linux #symlink

#python #django #linux #символическая ссылка

Вопрос:

Проблема

При попытке запустить одну из моих пользовательских команд управления 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. django/core/management/__init__.py Между строками 394 и 401 находится код, который вызывает это действие. В частности, это: os.path.dirname(settings_mod.__file__) .

2. @Jack Я согласен. К сожалению, я не вижу, как настроить Django или мою систему, чтобы я мог обслуживать свое приложение через символическую ссылку таким образом, os.path.dirname(settings_mod.__file__) который определяет правильный путь для меня. Код Django был написан в предположении, что модули Python похожи на пути к файлам..

3. Верно. Я просто пытался предоставить больше информации для тех, кто пытается ответить, поскольку у меня ее нет. Рассматривали ли вы возможность использования вашего контроля версий, чтобы заставить это работать? Mercurial, вероятно, лучше справился бы с поддержанием вашего приложения в актуальном состоянии, чем эта символическая ссылка / именование каталога.

Ответ №1:

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

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

Проблема в том, что __file__ возвращает символической ссылке относительный путь, который в зависимости от того, откуда он импортируется (внутри пути с символической ссылкой ..), вот как он сообщит, что это home. Поскольку каталоги являются базовой структурой модулей, если у вас есть каталог с __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