Каковы правильные разрешения и виртуальные хосты для запуска Django в подкаталоге?

Я пытаюсь установить и запустить Django в подкаталоге, чтобы он был отделен от статического html-сайта в корне, и у меня возникают проблемы с разрешениями на файлы/папки или виртуальными хостами

Эти два вопроса не помогли и очень старые: install django on subdirectory и Configure django on sub directory

Это проблема прав доступа к файлам/папкам или виртуальных хостов? Почему .py файлы не выполняются?


  • Работает Ubuntu 20.04.3 LTS
  • .
  • Apache2 уже установлен и работает
  • Python3 и Django установлены
  • libapache2-mod-wsgi установлен и включен
  • Apache перезапускался несколько раз

Я выполнил обычные команды оболочки для запуска проекта Django:

django-admin.py startproject contact

и затем я успешно запустил createsuperuser, collectstatic и т.д.

https://example.com/contact/index.html работает нормально,

Но вот что я получаю на example.com/contact/contact:

enter image description here

Вот структура моего файла:

enter image description here

settings.py:

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SECRET_KEY = '...'

DEBUG = True

ALLOWED_HOSTS = []

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'contact.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'contact.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

Это 000-default.conf от Apache2:

<VirtualHost *:80>
    
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    Alias /static /var/www/html/example.com/public_html/contact/static
    <Directory /var/www/html/example.com/public_html/contact/static>
        Require all granted
    </Directory>

    <Directory /var/www/html/example.com/public_html/contact/contact>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>

    WSGIDaemonProcess contact python-path=/var/www/html/example.com/public_html/contact python-home=/var/www/html/example.com/public_html/contact/contact
    
    WSGIProcessGroup contact
    
    WSGIScriptAlias /contact/contact /var/www/html/example.com/public_html/contact/contact/wsgi.py
    
    WSGISocketPrefix run/wsgi

</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Похоже, что директория имеет приоритет перед директивой WSGIScriptAlias /contact/contact /var/www/html/example.com/public_html/contact/contact/wsgi.py. Поскольку каталог /contact/contact существует в файловой системе, директива WSGIScriptAlias, похоже, не используется.

Вы можете попробовать переместить скрипты за пределы DocumentRoot, поскольку это также защищает исходный код файлов от раскрытия, если произойдет событие, подобное описанному выше. Кроме того, это позволяет избежать конфликтов между каталогами/папками в файловой системе и директивами *ScriptAlias.

Также, вы можете попробовать отключить 'redirect to slash for directories' с помощью DirectorySlash Off, а затем очистить кэш браузера.

Кроме того, вы уверены, что обращаетесь к http://example.com, а не к https://example.com? Если вы обращаетесь к https://, вам также нужно добавить WSGIScriptAlias /contact/contact /var/www/html/example.com/public_html/contact/contact/wsgi.py (и другие вещи) к <VirtualHost *:443> в default-ssl.conf или куда-нибудь еще, где они есть.

Одна строка вашего 000-default.conf определяет путь к исполняемому файлу python :

WSGIDaemonProcess contact python-path=/var/www/html/example.com/public_html/contact python-home=/var/www/html/example.com/public_html/contact/contact

Если вы хотите позволить apache найти python, используемый в оболочке, вам следует удалить аргумент python-path

WSGIDaemonProcess contact python-home=/var/www/html/example.com/public_html/contact/contact

Или сделайте так, чтобы он указывал на вашу установку python3

WSGIDaemonProcess contact python-path=/my/python3/path python-home=/var/www/html/example.com/public_html/contact/contact

Таким образом у вас перестанет появляться предупреждение об использовании python2.7, и это может помочь вашему проекту работать

Вы также должны убедиться, что ваш mod-wsgi был установлен с использованием python3, а не python2.7

Вот что наконец сработало для меня:

Мне нужно было добавить #added lines в wsgi.py (из https://www.metaltoad.com/blog/hosting-django-sites-apache )

import os

import sys #added

sys.path.append('/var/www/html/contact')  #added

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'contact.settings')

application = get_wsgi_application()

Вместо того, чтобы редактировать /etc/apache2/sites-available/default-ssl.conf, я отредактировал /etc/apache2/apache2.conf:

Alias /static /var/www/html/example.com/public_html/contact/static
Alias /media /var/www/html/example.com/public_html/contact/media

<Directory /var/www/html/example.com/public_html/contact/static>
    Require all granted
</Directory>

<Directory /var/www/html/example.com/public_html/contact/media>
    Require all granted
</Directory>

WSGIScriptAlias /contact  /var/www/html/example.com/public_html/contact/contact/wsgi.py process-group=contact

WSGIDaemonProcess contact  python-path=/var/www/html/example.com/public_html/contact

WSGIProcessGroup contact

<Directory  /var/www/html>
Options Indexes FollowSymLinks
AllowOverride all
Require all granted

<Files wsgi.py>
Require all granted
</Files>
</Directory>
Вернуться на верх