# How to add Wagtail into an existing Django project To install Wagtail completely from scratch, create a new Django project and an app within that project. For instructions on these tasks, see [Writing your first Django app](inv:django#intro/tutorial01). Your project directory will look like the following: ``` myproject/ myproject/ __init__.py settings.py urls.py wsgi.py myapp/ __init__.py models.py tests.py admin.py views.py manage.py ``` From your app directory, you can safely remove `admin.py` and `views.py`, since Wagtail will provide this functionality for your models. Configuring Django to load Wagtail involves adding modules and variables to `settings.py` and URL configuration to `urls.py`. For a more complete view of what's defined in these files, see [Django Settings](inv:django#topics/settings) and [Django URL Dispatcher](inv:django#topics/http/urls). What follows is a settings reference which skips many boilerplate Django settings. If you just want to get your Wagtail install up quickly without fussing with settings at the moment, see [](complete_example_config). ## Middleware (`settings.py`) ```python MIDDLEWARE = [ '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', 'django.middleware.security.SecurityMiddleware', 'wagtail.contrib.redirects.middleware.RedirectMiddleware', ] ``` Wagtail depends on the default set of Django middleware modules, to cover basic security and functionality such as login sessions. One additional middleware module is provided: **`RedirectMiddleware`** Wagtail provides a simple interface for adding arbitrary redirects to your site and this module makes it happen. ## Apps (`settings.py`) ```python INSTALLED_APPS = [ 'myapp', # your own app 'wagtail.contrib.forms', 'wagtail.contrib.redirects', 'wagtail.embeds', 'wagtail.sites', 'wagtail.users', 'wagtail.snippets', 'wagtail.documents', 'wagtail.images', 'wagtail.search', 'wagtail.admin', 'wagtail', 'taggit', 'modelcluster', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] ``` Wagtail requires several Django app modules, third-party apps, and defines several apps of its own. Wagtail was built to be modular, so many Wagtail apps can be omitted to suit your needs. Your own app (here `myapp`) is where you define your models, templates, static assets, template tags, and other custom functionality for your site. ### Wagtail Apps **`wagtail`** The core functionality of Wagtail, such as the `Page` class, the Wagtail tree, and model fields. **`wagtail.admin`** The administration interface for Wagtail, including page edit handlers. **`wagtail.documents`** The Wagtail document content type. **`wagtail.snippets`** Editing interface for non-Page models and objects. See [](Snippets). **`wagtail.users`** User editing interface. **`wagtail.images`** The Wagtail image content type. **`wagtail.embeds`** Module governing oEmbed and Embedly content in Wagtail rich text fields. **`wagtail.search`** Search framework for Page content. See [](wagtailsearch). **`wagtail.sites`** Management UI for Wagtail sites. **`wagtail.contrib.redirects`** Admin interface for creating arbitrary redirects on your site. **`wagtail.contrib.forms`** Models for creating forms on your pages and viewing submissions. See [Form builder](form_builder). ### Third-Party Apps **`taggit`** Tagging framework for Django. This is used internally within Wagtail for image and document tagging and is available for your own models as well. See [](tagging) for a Wagtail model recipe or the [Taggit Documentation](https://django-taggit.readthedocs.io/en/stable/). **`modelcluster`** Extension of Django ForeignKey relation functionality, which is used in Wagtail pages for on-the-fly related object creation. For more information, see [](inline_panels) or [the django-modelcluster github project page](https://github.com/wagtail/django-modelcluster). ## URL Patterns ```python from django.contrib import admin from wagtail import urls as wagtail_urls from wagtail.admin import urls as wagtailadmin_urls from wagtail.documents import urls as wagtaildocs_urls urlpatterns = [ path('django-admin/', admin.site.urls), path('admin/', include(wagtailadmin_urls)), path('documents/', include(wagtaildocs_urls)), # Optional URL for including your own vanilla Django urls/views re_path(r'', include('myapp.urls')), # For anything not caught by a more specific rule above, hand over to # Wagtail's serving mechanism re_path(r'', include(wagtail_urls)), ] ``` This block of code for your project's `urls.py` does a few things: - Load the vanilla Django admin interface to `/django-admin/` - Load the Wagtail admin and its various apps - Dispatch any vanilla Django apps you're using other than Wagtail which require their own URL configuration (this is optional, since Wagtail might be all you need) - Lets Wagtail handle any further URL dispatching. That's not everything you might want to include in your project's URL configuration, but it's what's necessary for Wagtail to flourish. (complete_example_config)= ## Ready to Use Example Configuration Files These two files should reside in your project directory (`myproject/myproject/`). ### `settings.py` ```python import os PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(PROJECT_DIR) DEBUG = True # Application definition INSTALLED_APPS = [ 'myapp', 'wagtail.contrib.forms', 'wagtail.contrib.redirects', 'wagtail.embeds', 'wagtail.sites', 'wagtail.users', 'wagtail.snippets', 'wagtail.documents', 'wagtail.images', 'wagtail.search', 'wagtail.admin', 'wagtail', 'taggit', 'modelcluster', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] MIDDLEWARE = [ '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', 'django.middleware.security.SecurityMiddleware', 'wagtail.contrib.redirects.middleware.RedirectMiddleware', ] ROOT_URLCONF = 'myproject.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.path.join(PROJECT_DIR, 'templates'), ], '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 = 'myproject.wsgi.application' # Database DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'myprojectdb', 'USER': 'postgres', 'PASSWORD': '', 'HOST': '', # Set to empty string for localhost. 'PORT': '', # Set to empty string for default. 'CONN_MAX_AGE': 600, # number of seconds database connections should persist for } } # Internationalization LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) STATICFILES_FINDERS = [ 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ] STATICFILES_DIRS = [ os.path.join(PROJECT_DIR, 'static'), ] STATIC_ROOT = os.path.join(BASE_DIR, 'static') STATIC_URL = '/static/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/' ADMINS = [ # ('Your Name', 'your_email@example.com'), ] MANAGERS = ADMINS # Default to dummy email backend. Configure dev/production/local backend # as per https://docs.djangoproject.com/en/stable/topics/email/#email-backends EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' # Hosts/domain names that are valid for this site; required if DEBUG is False ALLOWED_HOSTS = [] # Make this unique, and don't share it with anybody. SECRET_KEY = 'change-me' EMAIL_SUBJECT_PREFIX = '[Wagtail] ' INTERNAL_IPS = ('127.0.0.1', '10.0.2.2') # A sample logging configuration. The only tangible logging # performed by this configuration is to send an email to # the site admins on every HTTP 500 error when DEBUG=False. # See https://docs.djangoproject.com/en/stable/topics/logging for # more details on how to customize your logging configuration. LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse' } }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler' } }, 'loggers': { 'django.request': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': True, }, } } # WAGTAIL SETTINGS # This is the human-readable name of your Wagtail install # which welcomes users upon login to the Wagtail admin. WAGTAIL_SITE_NAME = 'My Project' # Replace the search backend #WAGTAILSEARCH_BACKENDS = { # 'default': { # 'BACKEND': 'wagtail.search.backends.elasticsearch8', # 'INDEX': 'myapp' # } #} # Wagtail email notifications from address # WAGTAILADMIN_NOTIFICATION_FROM_EMAIL = 'wagtail@myhost.io' # Wagtail email notification format # WAGTAILADMIN_NOTIFICATION_USE_HTML = True # Reverse the default case-sensitive handling of tags TAGGIT_CASE_INSENSITIVE = True ``` ### `urls.py` ```python from django.urls import include, path, re_path from django.conf.urls.static import static from django.views.generic.base import RedirectView from django.contrib import admin from django.conf import settings import os.path from wagtail import urls as wagtail_urls from wagtail.admin import urls as wagtailadmin_urls from wagtail.documents import urls as wagtaildocs_urls urlpatterns = [ path('django-admin/', admin.site.urls), path('admin/', include(wagtailadmin_urls)), path('documents/', include(wagtaildocs_urls)), # For anything not caught by a more specific rule above, hand over to # Wagtail's serving mechanism re_path(r'', include(wagtail_urls)), ] if settings.DEBUG: from django.contrib.staticfiles.urls import staticfiles_urlpatterns urlpatterns += staticfiles_urlpatterns() # tell gunicorn where static files are in dev mode urlpatterns += static(settings.MEDIA_URL + 'images/', document_root=os.path.join(settings.MEDIA_ROOT, 'images')) urlpatterns += [ path('favicon.ico', RedirectView.as_view(url=settings.STATIC_URL + 'myapp/images/favicon.ico')) ] ```