Django

Установить Django автоматически можно с помощью раздела «Установка CMS». В этой статье мы рассмотрим, как установить Django самостоятельно. Это дает несколько преимуществ, так как вы сможете выбрать любую версию и настроить всё под себя.

Виртуальное окружение

Сначала нужно поставить виртуальное окружение. Пройдите по нашей инструкции Python: установка virtualenv и активируйте окружение, потом переходите к установке Django.

Мы рекомендуем создавать окружение на одном уровне с public_html. Например, если файлы сайта находятся в сайт/public_html, то виртуальное окружение лучше создать в сайт/venv. Так вам будет проще следовать инструкции.

Виртуальное окружение позволит изолировать ваши сайты, а на некоторых серверах это единственный способ пользоваться пакетным менеджером pip.

Особенности хостинга

В первую очередь рассмотрим отличия Django на хостинге. Если вам не нужна инструкция по установке и настройке, то вы можете прочитать только этот пункт. Всё остальное можно найти в официальной документации Django.

Дальше в статье будет инструкция, в которой мы покажем создание сайта на хостинге, учитывая все особенности.

Как запускается сайт

Мы используем mod_wsgi, это модуль Apache. Из этого следует две особенности:

  1. Поддерживается только протокол WSGI, разместить ASGI не получится.
  2. WSGI-скрипт должен содержать вызываемый объект с названием application.

Рекомендуем использовать этот файл .htaccess, чтобы перенаправить все запросы на один файл. Также здесь указывается обработчик mod_wsgi для Python-файлов, потому что по умолчанию их обрабатывает mod_cgi.

Options +ExecCGI
AddHandler wsgi-script .py
 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /wsgi.py/$1 [QSA,PT]

Подключение виртуального окружения

Так как любые директивы mod_wsgi не работают в контексте файла .htaccess, подключить окружение можно только внутри WSGI-скрипта.

Пример, как это сделать:

activate_this = os.path.expanduser('~/сайт/venv/bin/activate_this.py')
exec(open(activate_this).read(), {'__file__': activate_this})

В этом коде нужно исправить путь до виртуального окружения.

Медленный SQLite

Python 3.10 в связке с mod_wsgi может очень медленно работать с базой SQLite. Для решения мы предлагаем установить pysqlite3:

pip install pysqlite3

Чтобы не переписывать весь код и не залезать в другие модули, добавьте код ниже в WSGI-скрипт после активации окружения. После этого любой импорт sqlite3 на самом деле импортирует pysqlite3.

import sys
 
__import__('pysqlite3')
sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')

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

Установка Django

Все команды нужно выполнять в командной строке после подключения по SSH. Когда подготовите виртуальное окружение, активируйте его и установите Django:

pip install django

Перейдите в директорию со своим сайтом:

cd сайт/public_html

Создайте новый проект. Название можно выбрать любое, здесь для примера используется web.

django-admin startproject web .

Переместите файл wsgi.py из чистой установки Django. Это будет точка входа в сайт. Обычно он лежит в подкаталоге проекта под названием wsgi.py.

mv web/wsgi.py .

Создайте файл .htaccess, чтобы перенаправить все запросы на wsgi.py. Поместите в него эти директивы:

Options +ExecCGI
AddHandler wsgi-script .py
 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /wsgi.py/$1 [QSA,PT]

На этом этапе структура проекта выглядит так:

.
├── public_html
│   ├── manage.py
│   ├── web
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   └── urls.py
│   └── wsgi.py
└── venv

Теперь нужно отредактировать wsgi.py. Так выглядит файл до изменений на Django 5.0:

import os
 
from django.core.wsgi import get_wsgi_application
 
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'web.settings')
 
application = get_wsgi_application()

Так он будет выглядеть после изменений:

import os
import sys
 
activate_this = os.path.expanduser('~/сайт/venv/bin/activate_this.py')
exec(open(activate_this).read(), {'__file__': activate_this})
 
sys.path.insert(1, os.path.expanduser('~/сайт/public_html/'))
 
from django.core.wsgi import get_wsgi_application
 
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'web.settings')
 
application = get_wsgi_application()

Первые две строки активируют виртуальное окружение, вам нужно будет исправить путь до него:

activate_this = os.path.expanduser('~/сайт/venv/bin/activate_this.py')
exec(open(activate_this).read(), {'__file__': activate_this})

Потом нужно добавить путь до корня проекта, его тоже нужно исправить. Подойдет путь, из которого можно импортировать проект.settings (в примере это web.settings).

sys.path.insert(1, os.path.expanduser('~/сайт/public_html/'))

На этом установка Django завершена, осталось его настроить.

Настройка Django

Настройки Django находятся в файле проект/settings.py. Все настройки ниже нужно записать в этот файл.

Общие настройки

Добавьте список разрешенных доменов в переменную ALLOWED_HOSTS:

ALLOWED_HOSTS = ['site.ru', 'site.com']

Вы можете разрешить все домены, чтобы не перечислять их:

ALLOWED_HOSTS = ['*']

На ваше усмотрение можно включить или выключить отладку. Чтобы включить её, найдите переменную DEBUG и задайте значение True:

DEBUG = True

Если ваш сайт не в разработке, и вы не решаете какую-то проблему, мы рекомендуем отключать отладку:

DEBUG = False

Статические файлы

Создайте две директории в корне сайта: static и media. Размещение именно в корне важно, чтобы веб-сервер смог их найти.

cd сайт/public_html
mkdir static media

После этого откройте файл settings.py и добавьте в него эти переменные:

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static/'
 
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media/'

Теперь соберите статику со всех проектов в созданные директории. Для этого активируйте виртуальное окружение и запустите файл manage.py:

python manage.py collectstatic

Теперь все статические файлы должны отображаться на сайте.

MySQL

Мы рекомендуем как можно раньше подключить MySQL вместо SQLite, это надежнее. Заранее подготовьте базу данных в панели управления (см. Создание базы данных).

Активируйте виртуальное окружение и установите пакет mysqlclient:

pip install mysqlclient

Откройте файл settings.py и найдите переменную DATABASES, по умолчанию там настроен SQLite:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

Перепишите всё под MySQL, подставив реквизиты своей базы данных. Шаблон:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'название_бд',
        'USER': 'название_бд',
        'PASSWORD': 'пароль',
        'HOST': '127.0.0.1',
        'PORT': 3306,
    }
}

Когда настроите соединение, запустите миграции. Так вы и проверите свои настройки, и создадите нужные таблицы для своего проекта:

python manage.py migrate

SQLite

На Python 3.10 работа с SQLite может быть очень медленная. Например, вход в админ-панель будет занимать много времени. Есть два варианта решения: перейти на MySQL или донастроить SQLite.

Чтобы Django нормально работал на SQLite, активируйте виртуальное окружение и установите пакет pysqlite3.

pip install pysqlite3

После этого откройте wsgi.py и добавьте в него эти строки после активации окружения:

__import__('pysqlite3')
sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')

Итоговый файл может выглядеть так:

import os
import sys
 
activate_this = os.path.expanduser('~/сайт/venv/bin/activate_this.py')
exec(open(activate_this).read(), {'__file__': activate_this})
 
sys.path.insert(1, os.path.expanduser('~/сайт/public_html/'))
 
__import__('pysqlite3')
sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')
 
from django.core.wsgi import get_wsgi_application
 
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'web.settings')
 
application = get_wsgi_application()

После этого каждый импорт sqlite3 на самом деле будет импортировать pysqlite3, это решает проблему с медленным сайтом.

Наконец, если вы еще этого не делали, примените миграции:

python manage.py migrate

Устранение ошибок

На время решения проблем советуем включить режим отладки. С ним вы увидите не только ошибку, но и другую полезную информацию: трассировку, переменные окружения. Включить отладку можно в файле settings.py:

DEBUG = True

Если режим отладки тоже не показывает ошибку, посмотрите логи Apache. Можно включить запись логов в панели управления или заказать их за прошедшее время (см. Получение логов).

На каждую ошибку будет несколько строк, поэтому как только вы найдете ошибку, посмотрите также на соседние строки. Например, так выглядит одна из ошибок:

xxxxxxx.xx [Tue Mar 19 14:00:00 2024] [error] [pid 1018652] src/server/mod_wsgi.c(3790): [client xxxxx] mod_wsgi (pid=1018652): Failed to exec Python script file '/home/x/xxxxxxx/public_html/wsgi.py'.
 
xxxxxxx.xx [Tue Mar 19 14:00:00 2024] [error] [pid 1018652] src/server/wsgi_logger.c(628): [client xxxxx] mod_wsgi (pid=1018652): Exception occurred processing WSGI script '/home/x/xxxxxxx/public_html/wsgi.py'.
 
xxxxxxx.xx [Tue Mar 19 14:00:00 2024] [error] [pid 1018652] src/server/wsgi_logger.c(147): [client xxxxx] Traceback (most recent call last):
 
xxxxxxx.xx [Tue Mar 19 14:00:00 2024] [error] [pid 1018652] src/server/wsgi_logger.c(147): [client xxxxx] File "/home/x/xxxxxxx/public_html/wsgi.py", line 7, in <module>
 
xxxxxxx.xx [Tue Mar 19 14:00:00 2024] [error] [pid 1018652] src/server/wsgi_logger.c(147): [client xxxxx] import dotenv
 
xxxxxxx.xx [Tue Mar 19 14:00:00 2024] [error] [pid 1018652] src/server/wsgi_logger.c(147): [client xxxxx] ModuleNotFoundError: No module named 'dotenv'

Если убрать информацию веб-сервера, останется такая ошибка:

Traceback (most recent call last):
  File "/home/x/xxxxxxx/public_html/wsgi.py", line 7, in <module>
    import dotenv
ModuleNotFoundError: No module named 'dotenv'

No module named 'имя_модуля'

Ошибка значит, что не установлен модуль, который импортирует сайт. Импортировать может и сам сайт, и другой модуль.

Проверьте, что в вашем виртуальном окружении действительно установлен нужный модуль. Это можно сделать с помощью команды:

pip freeze

Проверьте, что вы указали верные пути в файле wsgi.py. Нужны верные пути до виртуального окружения и корня проекта.

Если модуль установлен и с путями всё хорошо, проверьте в документации пакета, под каким именем его нужно импортировать. Например, пакет может называться python-dotenv, но импортировать нужно просто dotenv.

Проверьте в документации пакета, возможно, в вашей версии удалили или переименовали модуль, который вы импортируете. Установить другую версию можно по примеру:

pip install django==4.2.10

DisallowedHost at / Invalid HTTP_HOST header

Для решения нужно разрешить ваши домены в файле settings.py:

ALLOWED_HOSTS = ['site.ru', 'site.com']

Разрешить любой домен можно так:

ALLOWED_HOSTS = ['*']

AttributeError: module 'MySQLdb.constants.FIELD_TYPE' has no attribute 'JSON'

Активируйте окружение и обновите mysqlclient командой:

pip install -U mysqlclient