Debug true файл настроек django

Обновлено: 07.07.2024

Файл настроек Django содержит все настройки установки Django.Этот документ объясняет,как работают настройки и какие из них доступны.

Основы

Файл настроек-это просто модуль Python с переменными модульного уровня.

Вот пара примеров настроек:

DEBUG to False , you also need to properly set the ALLOWED_HOSTS setting. --> Если для DEBUG установлено значение False , вам также необходимо правильно установить параметр ALLOWED_HOSTS .

Поскольку файл настроек является модулем Python,применяется следующее:

Он может назначать настройки динамически,используя обычный синтаксис Python.Например:

Назначение настроек

DJANGO_SETTINGS_MODULE . --> Когда вы используете Django, вы должны указать ему, какие настройки вы используете. Сделайте это с помощью переменной среды DJANGO_SETTINGS_MODULE .

DJANGO_SETTINGS_MODULE should be in Python path syntax, e.g. mysite.settings . Note that the settings module should be on the Python import search path. --> Значение DJANGO_SETTINGS_MODULE должно быть в синтаксисе пути Python, например mysite.settings . Обратите внимание, что модуль настроек должен находиться на пути поиска импорта Python .

django-admin utility --> django-admin утилиты

При использовании django-admin вы можете либо установить переменную окружения один раз, либо явно передавать модуль настроек каждый раз, когда запускаете утилиту.

Пример (оболочка Unix Bash):

Пример (оболочка Windows):

--settings command-line argument to specify the settings manually: --> Используйте --settings командной строки --settings, чтобы указать настройки вручную:

mod_wsgi ) --> На сервере ( mod_wsgi )

os.environ : --> В вашей среде живого сервера вам нужно сообщить приложению WSGI, какой файл настроек использовать. Сделайте это с os.environ :

Прочитайте документацию по Django mod_wsgi для получения дополнительной информации и других общих элементов для приложения Django WSGI.

Настройки по умолчанию

django/conf/global_settings.py . --> Файл настроек Django не должен определять какие-либо настройки, если в этом нет необходимости. Каждый параметр имеет разумное значение по умолчанию. Эти значения по умолчанию django/conf/global_settings.py в модуле django / conf / global_settings.py .

Вот алгоритм, который Django использует при настройке компиляции:

  • global_settings.py . --> Загрузите настройки из global_settings.py .
  • Загружайте настройки из указанного файла настроек,при необходимости переопределяя глобальные настройки.

global_settings , because that’s redundant. --> Обратите внимание, что файл настроек не должен импортироваться из global_settings , потому что это избыточно.

Видя, какие настройки вы изменили

python manage.py diffsettings displays differences between the current settings file and Django’s default settings. --> Команда python manage.py diffsettings отображает различия между текущим файлом настроек и настройками Django по умолчанию.

diffsettings documentation. --> Для получения дополнительной информации см. Документацию по diffsettings .

Использование настроек в коде Python

django.conf.settings . Example: --> В ваших приложениях Django используйте настройки, импортировав объект django.conf.settings . Пример:

django.conf.settings isn’t a module – it’s an object. So importing individual settings is not possible: --> Обратите внимание, что django.conf.settings - это не модуль, а объект. Поэтому импорт отдельных настроек невозможен:

global_settings or your own settings file. django.conf.settings abstracts the concepts of default settings and site-specific settings; it presents a single interface. It also decouples the code that uses settings from the location of your settings. --> Также обратите внимание, что ваш код не должен импортироваться ни из global_settings , ни из вашего собственного файла настроек. django.conf.settings абстрагирует понятия настроек по умолчанию и настроек, специфичных для сайта; это представляет единый интерфейс. Он также разделяет код, который использует настройки, от расположения ваших настроек.

Изменение настроек во время выполнения

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

Единственное место,которое необходимо присвоить настройкам-это файл настроек.

Security

Поскольку файл настроек содержит конфиденциальную информацию, такую ​​как пароль базы данных, вы должны делать все возможное, чтобы ограничить доступ к нему. Например, измените права доступа к файлу, чтобы его могли прочитать только вы и пользователь вашего веб-сервера. Это особенно важно в среде виртуального хостинга.

Доступные настройки

Полный список доступных настроек см. В справочнике настроек .

Создание собственных настроек

Ничто не мешает вам создавать свои собственные настройки для своих собственных приложений Django, но следуйте этим рекомендациям:

  • Имена настроек должны быть все заглавными.
  • Не изобретайте уже существующую настройку.

Для настроек,которые являются последовательностями,сам Django использует списки,но это всего лишь соглашение.

Использование настроек без установки DJANGO_SETTINGS_MODULE

DJANGO_SETTINGS_MODULE environment variable. For example, if you’re using the template system by itself, you likely don’t want to have to set up an environment variable pointing to a settings module. --> В некоторых случаях может DJANGO_SETTINGS_MODULE обойти переменную среды DJANGO_SETTINGS_MODULE . Например, если вы используете систему шаблонов отдельно, вам, вероятно, не нужно настраивать переменную среды, указывающую на модуль настроек.

В этих случаях вы можете настроить параметры Django вручную. Сделайте это по телефону:

configure() as many keyword arguments as you’d like, with each keyword argument representing a setting and its value. Each argument name should be all uppercase, with the same name as the settings described above. If a particular setting is not passed to configure() and is needed at some later point, Django will use the default setting value. --> Передайте configure() столько аргументов ключевого слова, сколько вы хотите, чтобы каждый аргумент ключевого слова представлял параметр и его значение. Каждое имя аргумента должно быть в верхнем регистре с тем же именем, что и настройки, описанные выше. Если определенный параметр не передан в configure() и понадобится позже, Django будет использовать значение параметра по умолчанию.

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

settings.configure() , Django will not make any modifications to the process environment variables (see the documentation of TIME_ZONE for why this would normally occur). It’s assumed that you’re already in full control of your environment in these cases. --> Следовательно, при настройке с помощью settings.configure() Django не будет вносить никаких изменений в переменные среды процесса (см. Документацию TIME_ZONE , чтобы узнать, почему это обычно происходит). Предполагается, что в этих случаях вы уже полностью контролируете свою среду.

Пользовательские настройки по умолчанию

django.conf.global_settings , you can pass in a module or class that provides the default settings as the default_settings argument (or as the first positional argument) in the call to configure() . --> Если вы хотите, чтобы значения по умолчанию приходили не из django.conf.global_settings , вы можете передать модуль или класс, который предоставляет настройки по умолчанию, в качестве аргумента default_settings (или в качестве первого позиционного аргумента) в вызове configure() .

myapp_defaults , and the DEBUG setting is set to True , regardless of its value in myapp_defaults : --> В этом примере настройки по умолчанию берутся из myapp_defaults , а для параметра DEBUG установлено значение True , независимо от его значения в myapp_defaults :

myapp_defaults as a positional argument, is equivalent: --> Следующий пример, который использует myapp_defaults в качестве позиционного аргумента, эквивалентен:

django.conf.settings.global_settings for the full list. --> Обычно вам не нужно переопределять значения по умолчанию таким способом. Значения по умолчанию в Django достаточно ручные, чтобы их можно было безопасно использовать. Помните, что если вы передадите новый модуль по умолчанию, он полностью заменит значения по умолчанию для Django, поэтому вы должны указать значение для каждого возможного параметра, который может использоваться в импортируемом вами коде. Проверьте в django.conf.settings.global_settings для полного списка.

configure() or DJANGO_SETTINGS_MODULE is required --> Требуется либо configure() либо DJANGO_SETTINGS_MODULE

DJANGO_SETTINGS_MODULE environment variable, you must call configure() at some point before using any code that reads settings. --> Если вы не устанавливаете DJANGO_SETTINGS_MODULE среды DJANGO_SETTINGS_MODULE , вы должны в какой-то момент вызвать configure() прежде чем использовать любой код, считывающий настройки.

DJANGO_SETTINGS_MODULE and don’t call configure() , Django will raise an ImportError exception the first time a setting is accessed. --> Если вы не установите DJANGO_SETTINGS_MODULE и не вызовете configure() , Django ImportError исключение ImportError при первом доступе к параметру.

DJANGO_SETTINGS_MODULE , access settings values somehow, then call configure() , Django will raise a RuntimeError indicating that settings have already been configured. There is a property for this purpose: --> Если установить DJANGO_SETTINGS_MODULE , настройки доступа значения каким - то образом, то называть configure() , Django возбудит RuntimeError о том , что параметры уже настроены. Для этого есть свойство:

configure() more than once, or to call configure() after any setting has been accessed. --> Также ошибочно вызывать configure() более одного раза или вызывать configure() после обращения к любому параметру.

configure() or DJANGO_SETTINGS_MODULE . Not both, and not neither. --> Это сводится к следующему: используйте только одно из configure() или DJANGO_SETTINGS_MODULE . Ни то, ни другое.

django.setup() is required for “standalone” Django usage --> Вызов django.setup() необходим для «автономного» использования Django

Если вы используете компоненты Django «автономно» - например, пишете скрипт Python, который загружает некоторые шаблоны Django и отображает их, или используете ORM для извлечения некоторых данных - вам понадобится еще один шаг в дополнение к настройке параметров ,

DJANGO_SETTINGS_MODULE or called configure() , you’ll need to call django.setup() to load your settings and populate Django’s application registry. For example: --> После того, как вы установили DJANGO_SETTINGS_MODULE или вызвали configure() , вам нужно будет вызвать django.setup() чтобы загрузить ваши настройки и заполнить реестр приложений Django. Например:

django.setup() is only necessary if your code is truly standalone. When invoked by your Web server, or through django-admin, Django will handle this for you. --> Обратите внимание, что вызов django.setup() необходим, только если ваш код действительно автономен. Когда он вызывается вашим веб-сервером или через django-admin , Django справится с этим за вас.

django.setup() may only be called once. --> django.setup() может быть вызван только один раз.

django.setup() inside an if block: --> Поэтому избегайте размещения многократно используемой логики приложения в автономных сценариях, так что вам придется импортировать из сценария в другое место вашего приложения. Если вы не можете избежать этого, поместите вызов django.setup() внутри блока if :

Ссылка на настройки Содержит полный список основных и дополнительных настроек приложения.

Файл настроек Django содержит полную конфигурацию установленного проекта. Этот раздел описывает какие настройки доступны и как они работают.

Основы¶

Вот пример настроек:

Если установить False в DEBUG , вам также необходимо правильно определить ALLOWED_HOSTS .

Так как файл настроек это модуль Python, верно следующее:

Не допускаются ошибки синтаксиса Python.

Можно динамически определять настройки, используя обычный синтаксис Python. Например:

Можно импортировать значения из других файлов настроек.

Определения файла настроек¶

При использовании Django необходимо указать какие настройки вы используете. Используйте для этого переменную окружения DJANGO_SETTINGS_MODULE .

Значение DJANGO_SETTINGS_MODULE должно содержать путь импорта Python, например mysite.settings . Обратите внимание, модуль с настройками должен быть доступен для импорта.

Использование django-admin¶

При использовании django-admin вы можете один раз определить переменную окружения, или каждый раз явно указывать модуль с настройками.

Например (Unix Bash shell):

Например (Windows shell):

Используйте аргумент --settings , чтобы явно указать модуль с настройками:

Настройки сервера (mod_wsgi)¶

При настройках сервера вам понадобиться указать WSGI-приложению какой файл с настройками использовать. Для этого используйте os.environ :

Настройки по умолчанию¶

Проект Django не обязан определять какие-либо настройки, если в этом нет необходимости. Каждая настройка содержит значение по умолчанию. Эти значния можно найти в модуле django/conf/global_settings.py .

Django использует следующий алгоритм для загрузки настроек:

Загружает настройки из global_settings.py .

Загружает настройки из указанного файла настроек, перезаписывая значения по умолчанию.

Обратите внимание, файла с настройками не должен импортировать global_settings .

Узнать какие настройки вы поменяли¶

Есть простой способ узнать какие настройки вашего проекта отличаются от настроек по умолчанию. Команда python manage.py diffsettings показывает разницу между текущими настройками и настройками по умолчанию Django.

Подробности смотрите в описании diffsettings .

Использование настроек в коде Python¶

В вашем приложении Django вы можете использовать настройки, импортировав django.conf.settings . Например:

Также ваш код не должен использовать непосредственно global_settings или ваш модуль настроек. django.conf.settings предоставляет единый интерфейс работы с настройками, реализуя концепцию настроек по умолчанию и настроек проекта. Также разделяет код, который использует настройки, и сами настройки.

Изменяем настройки в процессе работы¶

Вам не следует менять настройки в процессе работы приложения. Например, не делайте следующее в представлении:

Безопасность¶

Файл настроек содержит конфиденциальную информацию, например, как пароль к базе данных, вы должны хранить его в безопасности. Например, поменяйте права доступа к файлу, чтобы только вы и пользователь веб-сервера имел к нему доступ. Это особенно важно для хостингов с общим окружением.

Доступные настройки¶

Полный список настроек смотрите в разделе о настройках.

Добавление собственных настроек¶

Вы можете добавлять настройки для ваших приложений Django. Просто следуйте правилам:

Названия настроек должны быть в верхнем регистре.

Не изобретайте заново существующие настройки.

Для настроек, которые представляют множество, Django использует списки, но это это не обязательно.

Использование настроек без DJANGO_SETTINGS_MODULE¶

В некоторых случаях вы можете не использовать переменную окружения DJANGO_SETTINGS_MODULE . Например, если вы используете систему шаблонов без Django, вряд ли вы захотите настраивать переменную окружения для настроек.

В этом случае вы можете явно определить настройки Django. Для этого вызовите:

django.conf.settings. configure (default_settings, **settings

Вы можете передать в configure() любое количество именованных аргументов, которые представляют настройки и их значения. Названия аргументов должны быть в верхнем регистре, как и названия настроек. Если какая-то настройка не была указанна в configure() , Django при необходимости будет использовать значение по умолчанию.

Настройка Django таким способом необходима, и рекомендуется использовать, при использовании части фреймверка в другом приложении.

При настройке через settings.configure() Django не меняет переменные окружения (смотрите описание TIME_ZONE , чтобы узнать когда это происходит). Подразумевается, что вы уже полностью контролируете свое окружение.

Собственные значения по умолчанию¶

Если вы хотите, чтобы значения по умолчанию загружались не с django.conf.global_settings , вы можете указать аргумент default_settings (или первый аргумент) при вызове configure() , который содержит модуль или класс со значениями по умолчанию.

В этом примере настройки по умолчанию загружаются с myapp_defaults , и настройка DEBUG равна True , несмотря на значение из myapp_defaults :

Следующий пример, который использует myapp_defaults как позиционный аргумент, аналогичен предыдущему:

Скорее всего вам не понадобится переопределять их таким способом. Настройки по умолчанию Django достаточно удобны, чтобы использовать их. Обратите внимание, если вы указали собственные настройки по умолчанию, они полностью заменяют настройки Django, поэтому необходимо указать все настройки, которые могут использовать в вашем коде. Полный список можно найти в модуле django.conf.settings.global_settings .

Требуется configure() или DJANGO_SETTINGS_MODULE¶

Если вы не указали переменную окружения DJANGO_SETTINGS_MODULE , вы должны вызывать configure() перед кодом, который использует настройки.

Если вы не указали DJANGO_SETTINGS_MODULE и не вызвали configure() , Django вызовет исключение ImportError при первом доступе к настройкам.

Если вы укажите DJANGO_SETTINGS_MODULE , обратитесь к настройкам, а затем вызовите configure() , Django вызовет исключение RuntimeError , указывая, что настройки уже определены. Для проверки этого существует свойство settings.configured .

Также нельзя вызывать configure() несколько раз, или вызывать configure() после обращения к настройкам.

Все сводится к правилам: используйте configure() , или DJANGO_SETTINGS_MODULE . Не оба, и хотя бы один.

После того, как вы указали переменную окружения DJANGO_SETTINGS_MODULE , или вызвали configure() , необходимы вызвать django.setup() , чтобы загрузить настройки и позволить Django загрузить приложения. Например:

Обратите внимание, django.setup() необходим, только если компоненты Django используются действительно отдельно. При запуске через Web-сервер, или django-admin, Django все сделает самостоятельно.

Содержит полный список основных настроек и настроек встроенных приложений.

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

Table of contents:

Управление настройками Django: проблемы

Разные окружения. Обычно в разработке используется несколько сред: локальная, dev, ci, qa, staging (промежуточная) , производственная и т. д. Каждая среда может иметь свои собственные конкретные настройки (например: DEBUG = True, более подробное ведение журнала, дополнительные приложения, некоторые фальшивые (mocked) данные и т. д.). Поэтому нам нужен подход, который позволяет сохранять все эти настройки Django для каждой среды отдельно.

Чувствительные данные. У нас есть SECRET_KEY в каждом проекте Django. Кроме того, могут быть пароли и токены БД для сторонних API, таких как Amazon или Twitter. Все данные желательно сохранять в системах VCS.

Обмен настройками между членами команды. Так же обычно нужен общий подход для устранения человеческих ошибок при работе с настройками. Например, разработчик может добавить стороннее приложение или некоторую интеграцию с API в одну конфигурацию и не добавляет определенные настройки в другие. В больших (или даже средних) проектах это может вызвать реальные проблемы.

Настройка конфигурации: разные подходы

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

settings_local.py

Это самый старый метод. Я использовал его, когда впервые настраивал проект Django на производственном сервере. Я видел, как многие люди использовали это в свое время, и я все еще вижу это сейчас.

Основная идея этого метода заключается в расширении всех специфических для среды настроек в файле settings_local.py, который игнорируется системой VCS. Вот пример:

Плюсы:

Недостатки:

  • settings_local.py отсутствует в VCS, поэтому вы можете потерять некоторые настройки среды Django.
  • Файл настроек Django представляет собой код Python, поэтому settings_local.py может иметь некоторую неочевидную логику.
  • У вас должен быть файл settings_local.example (в VCS), чтобы поделиться настройками по умолчанию со всеми разработчиками.

Отдельный файл настроек для каждой среды

Это расширение предыдущего подхода. Оно позволяет сохранять все конфигурации в VCS и делиться настройками по умолчанию между разработчиками.

В этом случае вы создаете каталог (пакет) settings со следующей структурой:

Чтобы запустить проект с определенной конфигурацией, вам нужно использовать дополнительный параметр:

Плюсы:

  • Все среды находятся в VCS.
  • Легко обмениваться настройками между разработчиками.

Недостатки:

  • Нужно найти способ обработки секретных паролей и токенов.
  • «Наследование» настроек может быть сложно отслеживать и контролировать.

Переменные окружения

Чтобы решить проблему с конфиденциальными данными, вы можете использовать переменные среды.

Это самый простой пример использования Python os.environ, и у него есть несколько проблем:

  1. Необходимо обработать исключения KeyError.
  2. Необходимо конвертировать типы вручную (см. Использование DATABASE_PORT).

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

Плюсы:

Недостатки:

  • Вы должны управлять совместным использованием конфигурации по умолчанию между разработчиками.

12 факторов

Как следует из названия, коллекция состоит из двенадцати частей:

  1. Базы кода (Codebase)
  2. Зависимости (Dependencies)
  3. Конфигурация (Config)
  4. Вспомогательные сервисы (Backing services)
  5. Сборка, релиз, запуск (Build, release, run)
  6. Процессы (Processes)
  7. Привязка к портам (Port binding)
  8. Параллелизм (Concurrency)
  9. Disposability
  10. Dev/prod паритет (Dev/prod parity)
  11. Логгирование (Logs)
  12. Процессы администратора (Admin processes)

Каждый пункт описывает рекомендуемый способ реализации определенного аспекта проекта. Некоторые из этих пунктов освещаются такими инструментами, как Django, Python, pip. Некоторые покрыты шаблонами проектирования или настройкой инфраструктуры. В контексте этой статьи нас интересует одна часть: Конфигурация.

django-environ

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

Теперь пришло время поговорить о наборе инструментов.

Написание кода с использованием os.environ иногда может быть сложным и потребовать дополнительных усилий для обработки ошибок. Вместо этого лучше использовать django-environment.

Технически это слияние следующих проектов:

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

файл settings.py перед:

файл settings.py после:

Файл .env:

Структура настроек

Вместо разделения настроек по средам вы можете разделить их по источникам: Django, сторонним приложениям (Celery, DRF и т. д.) И пользовательским настройкам.

файл __init__.py:

Каждый модуль может быть выполнен в виде пакета, и вы можете разбить его более детально:

Соглашения об именах

Именование переменных является одной из самых сложных частей разработки. Так называется наименование настроек. Мы не можем ссылаться на Django или сторонние приложения, но мы можем следовать этим простым правилам для наших пользовательских (проектных) настроек:

  • Дайте значимые имена вашим настройкам.
  • Всегда используйте префикс с именем проекта для пользовательских настроек (проекта).
  • Пишите описания ваших настроек в комментариях.

Плохой пример:

Хороший пример:

Измените MYAWESOMEPROJECT на ваше реальное название проекта.

Настройки Django: лучшие практики

  • Сохраняйте настройки в переменных среды.
  • Запишите значения по умолчанию для производственной конфигурации (исключая секретные ключи и токены).
  • Не задавайте жесткие настройки и не помещайте их в VCS.
  • Разделите настройки на группы: Django, third-party, проект.
  • Следуйте правилам именования для пользовательских (проектных) настроек.

Заключение

Используя подход с использованием переменных сред, вы можете легко перейти от монолитной архитектуры к микросервису, обернуть свой проект в контейнеры Docker и развернуть его на любой платформе хостинга VPS или Cloud, такой как: Amazon, Google Cloud или ваш собственный кластер Kubernetes.

Оригинальная статья: Alexander Ryabtsev Configuring Django Settings: Best Practices

Python Django: как изменить страницу ошибки 404?

Не теряя времени, создадим Django-проект. Откройте консоль и напишите эти команды:

Затем создайте Django-проект:

Запустите сервер со своим веб-приложением:


Стандартная страница приветствия фреймворка Django

Вы видите эту ошибку, потому что в вашем файле настроек Django установлено значение DEBUG = True. Измените это значение на False, и Django отобразит стандартную страницу 404.

Давайте сделаем то, что написано в отчёте об ошибке 404: отключим режим отладки Django, изменив значение константы DEBUG в файле настроек проекта settings.py , кроме этого, указываем адрес локального сервера в списке разрешенных адресов:

Замечание! Когда вы будете располагать своё веб-приложение на хостинге для доступа к нему настоящих пользователей, вам понадобится снова изменить константу ALLOWED_HOSTS : указать приобретенный домен в качестве элемента списка.

Это и есть та самая страница, которую мы сейчас настроим с помощью собственного пользовательского шаблона.

Создаём файл представлений views.py в папке mysite с помощью данной команды:

Ваш Django-проект теперь должен выглядеть примерно так:

Теперь пришло время добавить функцию-представление, которая будет обрабатывать ошибку 404. В файл mysite/views.py добавьте следующие строчки кода:

Также необходимо в файле urls.py директории Django-проекта mysite определить значение переменной handler404 :

В итоге файл mysite/urls.py должен выглядеть следующим образом:

Теперь необходимо указать Django, где именно находится ваша папка templates , поэтому в файле settings.py , в константе TEMPLATES следует обозначить значение ключа ‘DIRS’ следующим образом:

Перед тем, как переключиться на вкладку браузера для проверки только что созданного шаблона — убедитесь, что структура вашего проекта выглядит вот так:

После проверки структуры проекта — перейдите по любому из несуществующих путей вашего сайта: пользовательский HTML-шаблон 404.html обработает их все!


Пользовательская страница ошибки “404 Page Not Found”

Поздравляем — всё готово! Ваша собственноручно созданная страница 404 Page Not Found теперь используется каждый раз, когда пользователь обращается к несуществующему ресурсу.

Читайте также: