# Model reference

This document contains reference information for the model classes inside the `wagtail.models` module.

<a id="page-model-ref"></a>

## `Page`

### Database fields

### *class* wagtail.models.Page

#### title

(text)

Human-readable title of the page.

#### draft_title

(text)

Human-readable title of the page, incorporating any changes that have been made in a draft edit (in contrast to the `title` field, which for published pages will be the title as it exists in the current published version).

#### slug

(text)

This is used for constructing the page’s URL.

For example: `https://domain.com/blog/[my-slug]/`

#### content_type

(foreign key to `django.contrib.contenttypes.models.ContentType`)

A foreign key to the [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType) object that represents the specific model of this page.

#### live

(boolean)

A boolean that is set to `True` if the page is published.

Note: this field defaults to `True` meaning that any pages that are created programmatically will be published by default.

#### has_unpublished_changes

(boolean)

A boolean that is set to `True` when the page is either in draft or published with draft changes.

#### owner

(foreign key to user model)

A foreign key to the user that created the page.

#### first_published_at

(date/time)

The date/time when the page was first published.

#### last_published_at

(date/time)

The date/time when the page was last published.

#### seo_title

(text)

Alternate SEO-crafted title, for use in the page’s `<title>` HTML tag.

#### search_description

(text)

SEO-crafted description of the content, used for search indexing. This is also suitable for the page’s `<meta name="description">` HTML tag.

#### show_in_menus

(boolean)

Toggles whether the page should be included in site-wide menus, and is shown in the `promote_panels` within the Page editor.

Wagtail does not include any menu implementation by default, which means that this field will not do anything in the front facing content unless built that way in a specific Wagtail installation.

However, this is used by the [`in_menu()`](pages/queryset_reference.md#wagtail.query.PageQuerySet.in_menu) QuerySet filter to make it easier to query for pages that use this field.

Defaults to `False` and can be overridden on the model with `show_in_menus_default = True`.

#### NOTE
To set the global default for all pages, set `Page.show_in_menus_default = True` once where you first import the `Page` model.

#### locked

(boolean)

When set to `True`, the Wagtail editor will not allow any users to edit
the content of the page.

If `locked_by` is also set, only that user can edit the page.

#### locked_by

(foreign key to user model)

The user who has currently locked the page. Only this user can edit the page.

If this is `None` when `locked` is `True`, nobody can edit the page.

#### locked_at

(date/time)

The date/time when the page was locked.

#### alias_of

(foreign key to another page)

If set, this page is an alias of the page referenced in this field.

#### locale

(foreign key to Locale)

This foreign key links to the `Locale` object that represents the page language.

#### translation_key

(uuid)

A UUID that is shared between translations of a page. These are randomly generated
when a new page is created and copied when a translation of a page is made.

A `translation_key` value can only be used on one page in each locale.

### Methods and properties

In addition to the model fields provided, `Page` has many properties and methods that you may wish to reference, use, or override in creating your own models.

#### NOTE
See also [django-treebeard](https://django-treebeard.readthedocs.io/en/stable/index.html)’s [node API](https://django-treebeard.readthedocs.io/en/stable/api.html). `Page` is a subclass of [materialized path tree](https://django-treebeard.readthedocs.io/en/stable/mp_tree.html) nodes.

### *class* wagtail.models.Page

#### get_specific(deferred=False, copy_attrs=None, copy_attrs_exclude=None)

Return this object in its most specific subclassed form.

By default, a database query is made to fetch all field values for the
specific object. If you only require access to custom methods or other
non-field attributes on the specific object, you can use
`deferred=True` to avoid this query. However, any attempts to access
specific field values from the returned object will trigger additional
database queries.

By default, references to all non-field attribute values are copied
from current object to the returned one. This includes:

* Values set by a queryset, for example: annotations, or values set as
  a result of using `select_related()` or `prefetch_related()`.
* Any `cached_property` values that have been evaluated.
* Attributes set elsewhere in Python code.

For fine-grained control over which non-field values are copied to the
returned object, you can use `copy_attrs` to specify a complete list
of attribute names to include. Alternatively, you can use
`copy_attrs_exclude` to specify a list of attribute names to exclude.

If called on an object that is already an instance of the most specific
class, the object will be returned as is, and no database queries or
other operations will be triggered.

If the object was originally created using a model that has since
been removed from the codebase, an instance of the base class will be
returned (without any custom field values or other functionality
present on the original class). Usually, deleting these objects is the
best course of action, but there is currently no safe way for Wagtail
to do that at migration time.

#### specific

Returns this object in its most specific subclassed form with all field
values fetched from the database. The result is cached in memory.

#### specific_deferred

Returns this object in its most specific subclassed form without any
additional field values being fetched from the database. The result
is cached in memory.

#### specific_class

Return the class that this object would be if instantiated in its
most specific form.

If the model class can no longer be found in the codebase, and the
relevant `ContentType` has been removed by a database migration,
the return value will be `None`.

If the model class can no longer be found in the codebase, but the
relevant `ContentType` is still present in the database (usually a
result of switching between git branches without running or reverting
database migrations beforehand), the return value will be `None`.

#### cached_content_type

Return this object’s `content_type` value from the `ContentType`
model’s cached manager, which will avoid a database query if the
content type is already in memory.

#### page_type_display_name

A human-readable version of this page’s type.

#### get_url(request=None, current_site=None)

Return the ‘most appropriate’ URL for referring to this page from the pages we serve,
within the Wagtail backend and actual website templates;
this is the local URL (starting with ‘/’) if we’re only running a single site
(i.e. we know that whatever the current page is being served from, this link will be on the
same domain), and the full URL (with domain) if not.
Return `None` if the page is not routable.

Accepts an optional but recommended `request` keyword argument that, if provided, will
be used to cache site-level URL information (thereby avoiding repeated database / cache
lookups) and, via the `Site.find_for_request()` function, determine whether a relative
or full URL is most appropriate.

#### get_full_url(request=None)

Return the full URL (including protocol / domain) to this page, or `None` if it is not routable.

#### full_url

Return the full URL (including protocol / domain) to this page, or `None` if it is not routable.

#### relative_url(current_site, request=None)

Return the ‘most appropriate’ URL for this page taking into account the site we’re currently on;
a local URL if the site matches, or a fully qualified one otherwise.
Return `None` if the page is not routable.

Accepts an optional but recommended `request` keyword argument that, if provided, will
be used to cache site-level URL information (thereby avoiding repeated database / cache
lookups).

#### get_site()

Return the Site object that this page belongs to.

#### get_url_parts(request=None)

Determine the URL for this page and return it as a tuple of
`(site_id, site_root_url, page_url_relative_to_site_root)`.
Return `None` if the page is not routable, or return
`(site_id, None, None)` if `NoReverseMatch` exception is raised.

This is used internally by the `full_url`, `url`, `relative_url`
and `get_site` properties and methods; pages with custom URL routing
should override this method in order to have those operations return
the custom URLs.

Accepts an optional keyword argument `request`, which may be used
to avoid repeated database / cache lookups. Typically, a page model
that overrides `get_url_parts` should not need to deal with
`request` directly, and should just pass it to the original method
when calling `super`.

#### route(request, path_components)

#### serve(request, \*args, \*\*kwargs)

#### *static* route_for_request(request: [HttpRequest](https://docs.djangoproject.com/en/stable/ref/request-response/#django.http.HttpRequest), path: [str](https://docs.python.org/3/library/stdtypes.html#str)) → RouteResult | [None](https://docs.python.org/3/library/constants.html#None)

Find the page route for the given HTTP request object, and URL path. The route
result (page, args, and kwargs) will be cached via
`request._wagtail_route_for_request`.

#### *static* find_for_request(request: [HttpRequest](https://docs.djangoproject.com/en/stable/ref/request-response/#django.http.HttpRequest), path: [str](https://docs.python.org/3/library/stdtypes.html#str)) → [Page](#wagtail.models.Page) | [None](https://docs.python.org/3/library/constants.html#None)

Find the page for the given HTTP request object, and URL path. The full
page route will be cached via `request._wagtail_route_for_request`.

#### get_default_privacy_setting(request)

Set the default privacy setting for the page.

The method must return a dictionary with at least a ‘type’ key. The value must be one of the following values from [`PageViewRestriction`](#wagtail.models.PageViewRestriction)’s [`restriction_type`](#wagtail.models.PageViewRestriction.restriction_type):

- `BaseViewRestriction.NONE`: The page is public and can be accessed by anyone. (default) - ‘{“type”: BaseViewRestriction.NONE}’
- `BaseViewRestriction.LOGIN`: The page is private and can only be accessed by authenticated users. - ‘{“type”: BaseViewRestriction.LOGIN}’
- `BaseViewRestriction.PASSWORD`: The page is private and can only be accessed by users with a shared password. (requires additional `password` key in the dictionary) - ‘{“type”: BaseViewRestriction.PASSWORD, “password”: “[P@ssw0rd123](mailto:P@ssw0rd123)!”}’
- `BaseViewRestriction.GROUPS`: The page is private and can only be accessed by users in specific groups. (requires additional `groups` key with list of Group objects) - ‘{“type”: BaseViewRestriction.GROUPS, “groups”: [moderators, editors]}’

Example

```python
class BreadsIndexPage(Page):
    #...

    def get_default_privacy_setting(request):
        from wagtail.models import BaseViewRestriction
        # if the editor has the foo.add_bar permission set the default to groups with the moderators and editors group checked
        if request.user.has_perm("foo.add_bar"):
            moderators = Group.objects.filter(name="Moderators").first()
            editors = Group.objects.filter(name="Editors").first()
            return {"type": BaseViewRestriction.GROUPS, "groups": [moderators,editors]}
        else:
            return {"type": BaseViewRestriction.NONE}
```

#### context_object_name *= None*

Custom name for page instance in page’s `Context`.

#### get_context(request, \*args, \*\*kwargs)

#### get_template(request, \*args, \*\*kwargs)

#### get_admin_display_title()

Return the title for this page as it should appear in the admin backend;
override this if you wish to display extra contextual information about the page,
such as language. By default, returns `draft_title`.

#### allowed_http_methods *= [<HTTPMethod.DELETE>, <HTTPMethod.GET>, <HTTPMethod.HEAD>, <HTTPMethod.OPTIONS>, <HTTPMethod.PATCH>, <HTTPMethod.POST>, <HTTPMethod.PUT>]*

When customizing this attribute, developers are encouraged to use values from Python’s built-in `http.HTTPMethod` enum in the list, as it is more robust, and makes use of values that already exist in memory. For example:

```python
from http import HTTPMethod

class MyPage(Page):
    allowed_http_methods = [HTTPMethod.GET, HTTPMethod.OPTIONS]
```

The `http.HTTPMethod` enum wasn’t added until Python 3.11, so if your project uses an older version of Python, you can use uppercase strings instead. For example:

```python
class MyPage(Page):
    allowed_http_methods = ["GET", "OPTIONS"]
```

#### check_request_method(request, \*args, \*\*kwargs)

Checks the `method` attribute of the request against those supported
by the page (as defined by [`allowed_http_methods`](#wagtail.models.Page.allowed_http_methods)) and responds
accordingly.

If supported, `None` is returned, and the request is processed
normally. If not, a warning is logged and an `HttpResponseNotAllowed`
is returned, and any further request handling is terminated.

#### handle_options_request(request, \*args, \*\*kwargs)

Returns an `HttpResponse` with an `"Allow"` header containing the list of
supported HTTP methods for this page. This method is used instead of
[`serve()`](#wagtail.models.Page.serve) to handle requests when the `OPTIONS` HTTP verb is
detected (and [`HTTPMethod.OPTIONS`](https://docs.python.org/3/library/http.html#http.HTTPMethod) is
present in [`allowed_http_methods`](#wagtail.models.Page.allowed_http_methods) for this type of page).

#### preview_modes

A list of `(internal_name, display_name)` tuples for the modes in which
this object can be displayed for preview/moderation purposes. Ordinarily an object
will only have one display mode, but subclasses can override this -
for example, a page containing a form might have a default view of the form,
and a post-submission ‘thank you’ page.
Set to `[]` to completely disable previewing for this model.

#### default_preview_mode

The default preview mode to use in live preview.
This default is also used in areas that do not give the user the option of selecting a
mode explicitly, e.g. in the moderator approval workflow.
If `preview_modes` is empty, an `IndexError` will be raised.

#### preview_sizes

A list of dictionaries, each representing a preview size option for this object.
Override this property to customize the preview sizes.
Each dictionary in the list should include the following keys:

- `name`: A string representing the internal name of the preview size.
- `icon`: A string specifying the icon’s name for the preview size button.
- `device_width`: An integer indicating the device’s width in pixels.
- `label`: A string for the aria label on the preview size button.

```python
@property
def preview_sizes(self):
    return [
        {
            "name": "mobile",
            "icon": "mobile-icon",
            "device_width": 320,
            "label": "Preview in mobile size"
        },
        # Add more preview size dictionaries as needed.
    ]
```

#### default_preview_size

The default preview size name to use in live preview.
Defaults to `"mobile"`, which is the first one defined in `preview_sizes`.
If `preview_sizes` is empty, an `IndexError` will be raised.

#### serve_preview(request, mode_name)

Returns an HTTP response for use in object previews.

This method can be overridden to implement custom rendering and/or
routing logic.

Any templates rendered during this process should use the `request`
object passed here - this ensures that `request.user` and other
properties are set appropriately for the wagtail user bar to be
displayed/hidden. This request will always be a GET.

#### get_parent(update=False)

* **Returns:**
  the parent node of the current node object.
  Caches the result in the object itself to help in loops.

#### get_children()

* **Returns:**
  A queryset of all the node’s children

#### get_ancestors(inclusive=False)

Returns a queryset of the current page’s ancestors, starting at the root page
and descending to the parent, or to the current page itself if `inclusive` is true.

#### get_descendants(inclusive=False)

Returns a queryset of all pages underneath the current page, any number of levels deep.
If `inclusive` is true, the current page itself is included in the queryset.

#### get_siblings(inclusive=True)

Returns a queryset of all other pages with the same parent as the current page.
If `inclusive` is true, the current page itself is included in the queryset.

#### get_translations(inclusive=False)

Returns a queryset containing the translations of this instance.

#### get_translation(locale)

Finds the translation in the specified locale.

If there is no translation in that locale, this raises a `model.DoesNotExist` exception.

#### get_translation_or_none(locale)

Finds the translation in the specified locale.

If there is no translation in that locale, this returns `None`.

#### has_translation(locale)

Returns True if a translation exists in the specified locale.

#### copy_for_translation(locale, copy_parents=False, alias=False, exclude_fields=None)

Creates a copy of this page in the specified locale.

#### get_admin_default_ordering()

Returns the default sort order for child pages to be sorted in viewing the admin pages index and not seeing search results.

The following sort orders are available:

- `'content_type'`
- `'-content_type'`
- `'latest_revision_created_at'`
- `'-latest_revision_created_at'`
- `'live'`
- `'-live'`
- `'ord'`
- `'title'`
- `'-title'`

For example to make a page sort by title for all the child pages only if there are < 20 pages.

```python
class BreadsIndexPage(Page):
    def get_admin_default_ordering(self):
        if Page.objects.child_of(self).count() < 20:
            return 'title'
        return self.admin_default_ordering
```

#### admin_default_ordering

An attribute version for the method `get_admin_default_ordering()`, defaults to `'-latest_revision_created_at'`.

#### localized

Finds the translation in the current active language.

If there is no translation in the active language, self is returned.

Note: This will not return the translation if it is in draft.
If you want to include drafts, use the `.localized_draft` attribute instead.

#### localized_draft

Finds the translation in the current active language.

If there is no translation in the active language, self is returned.

Note: This will return translations that are in draft. If you want to exclude
these, use the `.localized` attribute.

#### search_fields

A list of fields to be indexed by the search engine. See Search docs [Indexing extra fields](../topics/search/indexing.md#wagtailsearch-indexing-fields)

#### subpage_types

A list of page models which can be created as children of this page type. For example, a `BlogIndex` page might allow a `BlogPage` as a child, but not a `JobPage`:

```python
class BlogIndex(Page):
    subpage_types = ['mysite.BlogPage', 'mysite.BlogArchivePage']
```

The creation of child pages can be blocked altogether for a given page by setting its subpage_types attribute to an empty array:

```python
class BlogPage(Page):
    subpage_types = []
```

#### parent_page_types

A list of page models which are allowed as parent page types. For example, a `BlogPage` may only allow itself to be created below the `BlogIndex` page:

```python
class BlogPage(Page):
    parent_page_types = ['mysite.BlogIndexPage']
```

Pages can block themselves from being created at all by setting parent_page_types to an empty array (this is useful for creating unique pages that should only be created once):

```python
class HiddenPage(Page):
    parent_page_types = []
```

To allow for a page to be only created under the root page (for example for `HomePage` models) set the `parent_page_type` to `['wagtailcore.Page']`.

```python
class HomePage(Page):
    parent_page_types = ['wagtailcore.Page']
```

#### *classmethod* can_exist_under(parent)

Checks if this page type can exist as a subpage under a parent page
instance.

See also: [`Page.can_create_at()`](#wagtail.models.Page.can_create_at) and [`Page.can_move_to()`](#wagtail.models.Page.can_move_to)

#### *classmethod* can_create_at(parent)

Checks if this page type can be created as a subpage under a parent
page instance.

#### can_move_to(parent)

Checks if this page instance can be moved to be a subpage of a parent
page instance.

#### get_route_paths()

Returns a list of paths that this page can be viewed at.

These values are combined with the dynamic portion of the page URL to
automatically create redirects when the page’s URL changes.

#### NOTE
If using `RoutablePageMixin`, you may want to override this method
to include the paths of popular routes.

#### NOTE
Redirect paths are ‘normalized’ to apply consistent ordering to GET parameters,
so you don’t need to include every variation. Fragment identifiers are discarded
too, so should be avoided.

#### password_required_template

Defines which template file should be used to render the login form for Protected pages using this model. This overrides the default, defined using `WAGTAIL_PASSWORD_REQUIRED_TEMPLATE` in your settings. See [Private pages](../advanced_topics/privacy.md#private-pages)

#### is_creatable

Controls if this page can be created through the Wagtail administration. Defaults to `True`, and is not inherited by subclasses. This is useful when using [multi-table inheritance](https://docs.djangoproject.com/en/stable/topics/db/models/#meta-and-multi-table-inheritance), to stop the base model from being created as an actual page.

#### max_count

Controls the maximum number of pages of this type that can be created through the Wagtail administration interface. This is useful when needing “allow at most 3 of these pages to exist”, or for singleton pages.

#### max_count_per_parent

Controls the maximum number of pages of this type that can be created under any one parent page.

#### private_page_options

> Controls what privacy options are available for the page type.

The following options are available:

- `'password'` - Can restrict to use a shared password
- `'groups'` - Can restrict to users in specific groups
- `'login'` - Can restrict to logged in users

> ```python
> class BreadPage(Page):
>     ...

>     # default
>     private_page_options = ['password', 'groups', 'login']

>     # disable shared password
>     private_page_options = ['groups', 'login']

>     # only shared password
>     private_page_options = ['password']

>     # no privacy options for this page model
>     private_page_options = []
> ```

#### exclude_fields_in_copy

An array of field names that will not be included when a Page is copied.
Useful when you have relations that do not use `ClusterableModel` or should not be copied.

```python
class BlogPage(Page):
    exclude_fields_in_copy = ['special_relation', 'custom_uuid']
```

The following fields will always be excluded in a copy - [‘id’, ‘path’, ‘depth’, ‘numchild’, ‘url_path’, ‘path’].

#### base_form_class

The form class is used as a base for editing Pages of this type in the Wagtail page editor.
This attribute can be set on a model to customize the Page editor form.
Forms must be a subclass of [`WagtailAdminPageForm`](../advanced_topics/customization/page_editing_interface.md#wagtail.admin.forms.WagtailAdminPageForm).
See [Customizing generated forms](../advanced_topics/customization/page_editing_interface.md#custom-edit-handler-forms) for more information.

#### with_content_json(content)

Returns a new version of the page with field values updated to reflect changes
in the provided `content` (which usually comes from a previously-saved
page revision).

Certain field values are preserved in order to prevent errors if the returned
page is saved, such as `id`, `content_type` and some tree-related values.
The following field values are also preserved, as they are considered to be
meaningful to the page as a whole, rather than to a specific revision:

* `draft_title`
* `live`
* `has_unpublished_changes`
* `owner`
* `locked`
* `locked_by`
* `locked_at`
* `latest_revision`
* `latest_revision_created_at`
* `first_published_at`
* `alias_of`
* `wagtail_admin_comments` (COMMENTS_RELATION_NAME)

#### save(clean=True, user=None, log_action=False, \*\*kwargs)

Writes the page to the database, performing additional housekeeping tasks to ensure data
integrity:

* `locale`, `draft_title` and `slug` are set to default values if not provided, with `slug`
  being generated from the title with a suffix to ensure uniqueness within the parent page
  where necessary
* The `url_path` field is set based on the `slug` and the parent page
* If the `slug` has changed, the `url_path` of this page and all descendants is updated and
  a [page_slug_changed](signals.md#page-slug-changed) signal is sent

New pages should be saved by passing the unsaved page instance to the
[`add_child()`](https://django-treebeard.readthedocs.io/en/stable/mp_tree.html#treebeard.mp_tree.MP_Node.add_child)
or [`add_sibling()`](https://django-treebeard.readthedocs.io/en/stable/mp_tree.html#treebeard.mp_tree.MP_Node.add_sibling) method of an existing page, which will correctly update
the fields responsible for tracking the page’s location in the tree.

If `clean=False` is passed, the page is saved without validation. This is appropriate for updates that only
change metadata such as latest_revision while keeping content and page location unchanged.

If `clean=True` is passed (the default), and the page has `live=True` set, the page is validated using
[`full_clean()`](https://docs.djangoproject.com/en/stable/ref/models/instances/#django.db.models.Model.full_clean) before saving.

If `clean=True` is passed, and the page has `live=False` set, only the title and slug fields are validated.

#### copy(recursive=False, to=None, update_attrs=None, copy_revisions=True, keep_live=True, user=None, process_child_object=None, exclude_fields=None, log_action='wagtail.copy', reset_translation_key=True)

Copies a given page

* **Parameters:**
  **log_action** – flag for logging the action. Pass None to skip logging. Can be passed an action string. Defaults to `'wagtail.copy'`.

#### move(new_parent, pos=None)

Move a page and all its descendants to a new parent.
See [`django-treebeard`](https://django-treebeard.readthedocs.io/en/stable/api.html#treebeard.models.Node.move) for more information.

#### create_alias(\*, recursive=False, parent=None, update_slug=None, update_locale=None, user=None, log_action='wagtail.create_alias', reset_translation_key=True, \_mpnode_attrs=None)

#### update_aliases(\*, revision=None, \_content=None, \_updated_ids=None)

Publishes all aliases that follow this page with the latest content from this page.

This is called by Wagtail whenever a page with aliases is published.

* **Parameters:**
  **revision** ([*Revision*](#wagtail.models.Revision) *,* *Optional*) – The revision of the original page that we are updating to (used for logging purposes)

#### get_cache_key_components()

The components of a [`Page`](#wagtail.models.Page) which make up the [`cache_key`](#wagtail.models.Page.cache_key). Any change to a
page should be reflected in a change to at least one of these components.

#### cache_key

A generic cache key to identify a page in its current state.
Should the page change, so will the key.

Customizations to the cache key should be made in [`get_cache_key_components`](#wagtail.models.Page.get_cache_key_components).

<a id="site-model-ref"></a>

## `Site`

The `Site` model is useful for multi-site installations as it allows an administrator to configure which part of the tree to use for each hostname that the server responds on.

The [`find_for_request()`](#wagtail.models.Site.find_for_request) function returns the Site object that will handle the given HTTP request.

### Database fields

### *class* wagtail.models.Site

#### hostname

(text)

This is the hostname of the site, excluding the scheme, port, and path.

For example: `www.mysite.com`

#### NOTE
If you’re looking for how to get the root url of a site, use the [`root_url`](#wagtail.models.Site.root_url) attribute.

#### port

(number)

This is the port number that the site responds on.

#### site_name

(text - optional)

A human-readable name for the site. This is not used by Wagtail itself, but is suitable for use on the site front-end, such as in `<title>` elements.

For example: `Rod's World of Birds`

#### root_page

(foreign key to [`Page`](#wagtail.models.Page))

This is a link to the root page of the site. This page will be what appears at the `/` URL on the site and would usually be a homepage.

#### is_default_site

(boolean)

This is set to `True` if the site is the default. Only one site can be the default.

The default site is used as a fallback in situations where a site with the required hostname/port couldn’t be found.

### Methods and properties

### *class* wagtail.models.Site

#### *static* find_for_request(request)

Find the site object responsible for responding to this HTTP
request object. Try:

* unique hostname first
* then hostname and port
* if there is no matching hostname at all, or no matching
  hostname:port combination, fall back to the unique default site,
  or raise an exception

NB this means that high-numbered ports on an extant hostname may
still be routed to a different hostname which is set as the default

The site will be cached via request._wagtail_site

#### root_url

This returns the URL of the site. It is calculated from the [`hostname`](#wagtail.models.Site.hostname) and the [`port`](#wagtail.models.Site.port) fields.

The scheme part of the URL is calculated based on value of the [`port`](#wagtail.models.Site.port) field:

- 80 = `http://`
- 443 = `https://`
- Everything else will use the `http://` scheme and the port will be appended to the end of the hostname (for example `http://mysite.com:8000/`)

#### *static* get_site_root_paths()

Return a list of SiteRootPath instances, most specific path
first - used to translate url_paths into actual URLs with hostnames.

Each root path is an instance of the SiteRootPath named tuple,
and have the following attributes:

- `site_id` - The ID of the Site record
- `root_path` - The internal URL path of the site’s home page (for example ‘/home/’)
- `root_url` - The scheme/domain name of the site (for example ‘[https://www.example.com/](https://www.example.com/)’)
- `language_code` - The language code of the site (for example ‘en’)

<a id="locale-model-ref"></a>

## `Locale`

The `Locale` model defines the set of languages and/or locales that can be used on a site.
Each `Locale` record corresponds to a “language code” defined in the [WAGTAIL_CONTENT_LANGUAGES](settings.md#wagtail-content-languages-setting) setting.

Wagtail will initially set up one `Locale` to act as the default language for all existing content.
This first locale will automatically pick the value from `WAGTAIL_CONTENT_LANGUAGES` that most closely matches the site primary language code defined in `LANGUAGE_CODE`.
If the primary language code is changed later, Wagtail will **not** automatically create a new `Locale` record or update an existing one.

Before internationalization is enabled, all pages use this primary `Locale` record.
This is to satisfy the database constraints and make it easier to switch internationalization on at a later date.

### Changing `WAGTAIL_CONTENT_LANGUAGES`

Languages can be added or removed from `WAGTAIL_CONTENT_LANGUAGES` over time.

Before removing an option from `WAGTAIL_CONTENT_LANGUAGES`, it’s important that the `Locale`
record is updated to use a different content language or is deleted.
Any `Locale` instances that have invalid content languages are automatically filtered out from all
database queries making them unable to be edited or viewed.

### Methods and properties

### *class* wagtail.models.Locale

#### language_code

The language code that represents this locale

The language code can either be a language code on its own (such as `en`, `fr`),
or it can include a region code (such as `en-gb`, `fr-fr`).

#### *classmethod* get_default()

Returns the default Locale based on the site’s `LANGUAGE_CODE` setting.

#### *classmethod* get_active()

Returns the Locale that corresponds to the currently activated language in Django.

#### language_name

Uses data from `django.conf.locale` to return the language name in
English. For example, if the object’s `language_code` were `"fr"`,
the return value would be `"French"`.

Raises `KeyError` if `django.conf.locale` has no information
for the object’s `language_code` value.

#### language_name_local

Uses data from `django.conf.locale` to return the language name in
the language itself. For example, if the `language_code` were
`"fr"` (French), the return value would be `"français"`.

Raises `KeyError` if `django.conf.locale` has no information
for the object’s `language_code` value.

#### language_name_localized

Uses data from `django.conf.locale` to return the language name in
the currently active language. For example, if `language_code` were
`"fr"` (French), and the active language were `"da"` (Danish), the
return value would be `"Fransk"`.

Raises `KeyError` if `django.conf.locale` has no information
for the object’s `language_code` value.

#### is_default

Returns a boolean indicating whether this object is the default locale.

#### is_active

Returns a boolean indicating whether this object is the currently active locale.

#### is_bidi

Returns a boolean indicating whether the language is bi-directional.

#### get_display_name() → [str](https://docs.python.org/3/library/stdtypes.html#str)

## `TranslatableMixin`

`TranslatableMixin` is an abstract model that can be added to any non-page Django model to make it translatable.
Pages already include this mixin, so there is no need to add it.

For a non-page model to be translatable in the admin, it must also be [registered as a snippet](../topics/snippets/registering.md#wagtailsnippets-registering). See also [Translatable snippets](../advanced_topics/i18n.md#translatable-snippets).

### Database fields

### *class* wagtail.models.TranslatableMixin

#### locale

(Foreign Key to [`wagtail.models.Locale`](#wagtail.models.Locale))

For pages, this defaults to the locale of the parent page.

#### translation_key

(uuid)

A UUID that is randomly generated whenever a new model instance is created.
This is shared with all translations of that instance so can be used for querying translations.

The `translation_key` and `locale` fields have a unique key constraint to prevent the object from being translated into a language more than once.

#### NOTE
This is currently enforced via [`unique_together`](https://docs.djangoproject.com/en/stable/ref/models/options/#django.db.models.Options.unique_together) in `TranslatableMixin.Meta`, but may be replaced with a [`UniqueConstraint`](https://docs.djangoproject.com/en/stable/ref/models/constraints/#django.db.models.UniqueConstraint) in `TranslatableMixin.Meta.constraints` in the future.

If your model defines a [`Meta` class](https://docs.djangoproject.com/en/stable/ref/models/options/) (either with a new definition or inheriting `TranslatableMixin.Meta` explicitly), be mindful when setting `unique_together` or [`constraints`](https://docs.djangoproject.com/en/stable/ref/models/options/#django.db.models.Options.constraints). Ensure that there is either a `unique_together` or a `UniqueConstraint` (not both) on `translation_key` and `locale`. There is a system check for this.

### Methods and properties

### *class* wagtail.models.TranslatableMixin

#### get_translations(inclusive=False)

Returns a queryset containing the translations of this instance.

#### get_translation(locale)

Finds the translation in the specified locale.

If there is no translation in that locale, this raises a `model.DoesNotExist` exception.

#### get_translation_or_none(locale)

Finds the translation in the specified locale.

If there is no translation in that locale, this returns `None`.

#### has_translation(locale)

Returns True if a translation exists in the specified locale.

#### copy_for_translation(locale, exclude_fields=None)

Creates a copy of this instance with the specified locale.

Note that the copy is initially unsaved.

#### *classmethod* get_translation_model()

Returns this model’s “Translation model”.

The “Translation model” is the model that has the `locale` and
`translation_key` fields.
Typically this would be the current model, but it may be a
super-class if multi-table inheritance is in use (as is the case
for `wagtailcore.Page`).

#### localized

Finds the translation in the current active language.

If there is no translation in the active language, self is returned.

Note: This will not return the translation if it is in draft.
If you want to include drafts, use the `.localized_draft` attribute instead.

## `PreviewableMixin`

`PreviewableMixin` is a mixin class that can be added to any non-page Django model to allow previewing its instances.
Pages already include this mixin, so there is no need to add it.

For a non-page model to be previewable in the admin, it must also be [registered as a snippet](../topics/snippets/registering.md#wagtailsnippets-registering). See also [Making snippets previewable](../topics/snippets/features.md#wagtailsnippets-making-snippets-previewable).

### Methods and properties

### *class* wagtail.models.PreviewableMixin

#### preview_modes

A list of `(internal_name, display_name)` tuples for the modes in which
this object can be displayed for preview/moderation purposes. Ordinarily an object
will only have one display mode, but subclasses can override this -
for example, a page containing a form might have a default view of the form,
and a post-submission ‘thank you’ page.
Set to `[]` to completely disable previewing for this model.

#### default_preview_mode

The default preview mode to use in live preview.
This default is also used in areas that do not give the user the option of selecting a
mode explicitly, e.g. in the moderator approval workflow.
If `preview_modes` is empty, an `IndexError` will be raised.

#### preview_sizes

A list of dictionaries, each representing a preview size option for this object.
Override this property to customize the preview sizes.
Each dictionary in the list should include the following keys:

- `name`: A string representing the internal name of the preview size.
- `icon`: A string specifying the icon’s name for the preview size button.
- `device_width`: An integer indicating the device’s width in pixels.
- `label`: A string for the aria label on the preview size button.

```python
@property
def preview_sizes(self):
    return [
        {
            "name": "mobile",
            "icon": "mobile-icon",
            "device_width": 320,
            "label": "Preview in mobile size"
        },
        # Add more preview size dictionaries as needed.
    ]
```

#### default_preview_size

The default preview size name to use in live preview.
Defaults to `"mobile"`, which is the first one defined in `preview_sizes`.
If `preview_sizes` is empty, an `IndexError` will be raised.

#### is_previewable()

Returns `True` if at least one preview mode is specified in `preview_modes`.

#### get_preview_context(request, mode_name)

Returns a context dictionary for use in templates for previewing this object.

By default, this returns a dictionary containing the `request` and
and the `object` itself.

#### get_preview_template(request, mode_name)

Returns a template to be used when previewing this object.

Subclasses of `PreviewableMixin` must override this method to return the
template name to be used in the preview. Alternatively, subclasses can also
override the `serve_preview` method to completely customise the preview
rendering logic.

#### serve_preview(request, mode_name)

Returns an HTTP response for use in object previews.

This method can be overridden to implement custom rendering and/or
routing logic.

Any templates rendered during this process should use the `request`
object passed here - this ensures that `request.user` and other
properties are set appropriately for the wagtail user bar to be
displayed/hidden. This request will always be a GET.

## `RevisionMixin`

`RevisionMixin` is an abstract model that can be added to any non-page Django model to allow saving revisions of its instances.
Pages already include this mixin, so there is no need to add it.

For a non-page model to be revisionable in the admin, it must also be [registered as a snippet](../topics/snippets/registering.md#wagtailsnippets-registering). See also [Saving revisions of snippets](../topics/snippets/features.md#wagtailsnippets-saving-revisions-of-snippets).

### Database fields

### *class* wagtail.models.RevisionMixin

#### latest_revision

(foreign key to [`Revision`](#wagtail.models.Revision))

This points to the latest revision created for the object. This reference is stored in the database for performance optimization.

### Methods and properties

### *class* wagtail.models.RevisionMixin

#### \_revisions

A default `GenericRelation` for the purpose of automatically deleting
revisions when the object is deleted. This is not used to query the object’s
revisions. Instead, the [`revisions()`](#wagtail.models.RevisionMixin.revisions) property is used for that purpose.
As such, this default relation is considered private.

This `GenericRelation` does not have a
[`related_query_name`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericRelation.related_query_name),
so it cannot be used for reverse-related queries from `Revision` back to
this model. If the feature is desired, subclasses can define their own
`GenericRelation` to `Revision` with a custom `related_query_name`.

#### revisions

Returns revisions that belong to the object. For non-page models, this
is done by querying the [`Revision`](#wagtail.models.Revision) model directly
rather than using a
[`GenericRelation`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericRelation), to avoid
[a known limitation](https://code.djangoproject.com/ticket/31269) in
Django for models with multi-table inheritance where the relation’s
content type may not match the instance’s type.

#### save_revision(user=None, approved_go_live_at=None, changed=True, log_action=False, previous_revision=None, clean=True, overwrite_revision=None)

Creates and saves a revision.

* **Parameters:**
  * **user** – The user performing the action.
  * **approved_go_live_at** – The date and time the revision is approved to go live.
  * **changed** – Indicates whether there were any content changes.
  * **log_action** – Flag for logging the action. Pass `True` to also create a log entry. Can be passed an action string.
    Defaults to `"wagtail.edit"` when no `previous_revision` param is passed, otherwise `"wagtail.revert"`.
  * **previous_revision** ([*Revision*](#wagtail.models.Revision)) – Indicates a revision reversal. Should be set to the previous revision instance.
  * **clean** – Set this to `False` to skip cleaning object content before saving this revision.
* **Returns:**
  The newly created revision.

#### get_latest_revision_as_object()

Returns the latest revision of the object as an instance of the model.
If no latest revision exists, returns the object itself.

#### with_content_json(content)

Returns a new version of the object with field values updated to reflect changes
in the provided `content` (which usually comes from a previously-saved revision).

Certain field values are preserved in order to prevent errors if the returned
object is saved, such as `id`. The following field values are also preserved,
as they are considered to be meaningful to the object as a whole, rather than
to a specific revision:

* `latest_revision`

If [`TranslatableMixin`](#wagtail.models.TranslatableMixin) is applied, the following field values
are also preserved:

* `translation_key`
* `locale`

## `DraftStateMixin`

`DraftStateMixin` is an abstract model that can be added to any non-page Django model to allow its instances to have unpublished changes.
This mixin requires [`RevisionMixin`](#wagtail.models.RevisionMixin) to be applied. Pages already include this mixin, so there is no need to add it.

For a non-page model to have publishing features in the admin, it must also be [registered as a snippet](../topics/snippets/registering.md#wagtailsnippets-registering). See also [Saving draft changes of snippets](../topics/snippets/features.md#wagtailsnippets-saving-draft-changes-of-snippets).

### Database fields

### *class* wagtail.models.DraftStateMixin

#### live

(boolean)

A boolean that is set to `True` if the object is published.

Note: this field defaults to `True` meaning that any objects that are created programmatically will be published by default.

#### live_revision

(foreign key to [`Revision`](#wagtail.models.Revision))

This points to the revision that is currently live.

#### has_unpublished_changes

(boolean)

A boolean that is set to `True` when the object is either in draft or published with draft changes.

#### first_published_at

(date/time)

The date/time when the object was first published.

#### last_published_at

(date/time)

The date/time when the object was last published.

### Methods and properties

### *class* wagtail.models.DraftStateMixin

#### publish(revision, user=None, changed=True, log_action=True, previous_revision=None, skip_permission_checks=False)

Publish a revision of the object by applying the changes in the revision to the live object.

* **Parameters:**
  * **revision** ([*Revision*](#wagtail.models.Revision)) – Revision to publish.
  * **user** – The publishing user.
  * **changed** – Indicated whether content has changed.
  * **log_action** – Flag for the logging action, pass `False` to skip logging.
  * **previous_revision** ([*Revision*](#wagtail.models.Revision)) – Indicates a revision reversal. Should be set to the previous revision instance.

#### unpublish(set_expired=False, commit=True, user=None, log_action=True)

Unpublish the live object.

* **Parameters:**
  * **set_expired** – Mark the object as expired.
  * **commit** – Commit the changes to the database.
  * **user** – The unpublishing user.
  * **log_action** – Flag for the logging action, pass `False` to skip logging.

#### with_content_json(content)

Similar to [`RevisionMixin.with_content_json()`](#wagtail.models.RevisionMixin.with_content_json),
but with the following fields also preserved:

* `live`
* `has_unpublished_changes`
* `first_published_at`

## `LockableMixin`

`LockableMixin` is an abstract model that can be added to any non-page Django model to allow its instances to be locked.
Pages already include this mixin, so there is no need to add it. See [Locking snippets](../topics/snippets/features.md#wagtailsnippets-locking-snippets) for more details.

For a non-page model to be lockable in the admin, it must also be [registered as a snippet](../topics/snippets/registering.md#wagtailsnippets-registering). See also [Locking snippets](../topics/snippets/features.md#wagtailsnippets-locking-snippets).

### Database fields

### *class* wagtail.models.LockableMixin

#### locked

(boolean)

A boolean that is set to `True` if the object is locked.

#### locked_at

(date/time)

The date/time when the object was locked.

#### locked_by

(foreign key to user model)

The user who locked the object.

### Methods and properties

### *class* wagtail.models.LockableMixin

#### get_lock()

Returns a sub-class of `BaseLock` if the instance is locked, otherwise `None`.

#### with_content_json(content)

Similar to [`RevisionMixin.with_content_json()`](#wagtail.models.RevisionMixin.with_content_json),
but with the following fields also preserved:

* `locked`
* `locked_at`
* `locked_by`

## `WorkflowMixin`

`WorkflowMixin` is a mixin class that can be added to any non-page Django model to allow its instances to be submitted to workflows.
This mixin requires [`RevisionMixin`](#wagtail.models.RevisionMixin) and [`DraftStateMixin`](#wagtail.models.DraftStateMixin) to be applied. Pages already include this mixin, so there is no need to add it. See [Enabling workflows for snippets](../topics/snippets/features.md#wagtailsnippets-enabling-workflows) for more details.

For a non-page model to have workflow features in the admin, it must also be [registered as a snippet](../topics/snippets/registering.md#wagtailsnippets-registering). See also [Enabling workflows for snippets](../topics/snippets/features.md#wagtailsnippets-enabling-workflows).

### Methods and properties

### *class* wagtail.models.WorkflowMixin

#### *classmethod* get_default_workflow()

Returns the active workflow assigned to the model.

For non-`Page` models, workflows are assigned to the model’s content type,
thus shared across all instances instead of being assigned to individual
instances (unless [`get_workflow()`](#wagtail.models.WorkflowMixin.get_workflow) is overridden).

This method is used to determine the workflow to use when creating new
instances of the model. On `Page` models, this method is unused as the
workflow can be determined from the parent page’s workflow.

#### has_workflow

Returns ``True`` if the object has an active workflow assigned, otherwise ``False``.

#### get_workflow()

Returns the active workflow assigned to the object.

#### \_workflow_states

A default `GenericRelation` for the purpose of automatically deleting
workflow states when the object is deleted. This is not used to query the
object’s workflow states. Instead, the [`workflow_states()`](#wagtail.models.WorkflowMixin.workflow_states) property is
used for that purpose. As such, this default relation is considered private.

This `GenericRelation` does not have a
[`related_query_name`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericRelation.related_query_name),
so it cannot be used for reverse-related queries from `WorkflowState` back
to this model. If the feature is desired, subclasses can define their own
`GenericRelation` to `WorkflowState` with a custom
`related_query_name`.

#### workflow_states

Returns workflow states that belong to the object. For non-page models,
this is done by querying the [`WorkflowState`](#wagtail.models.WorkflowState)
model directly rather than using a
[`GenericRelation`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericRelation), to avoid
[a known limitation](https://code.djangoproject.com/ticket/31269) in
Django for models with multi-table inheritance where the relation’s
content type may not match the instance’s type.

#### workflow_in_progress

Returns ``True`` if a workflow is in progress on the current object, otherwise ``False``.

#### current_workflow_state

Returns the in progress or needs changes workflow state on this object, if it exists.

#### current_workflow_task_state

Returns (specific class of) the current task state of the workflow on this object, if it exists.

#### current_workflow_task

Returns (specific class of) the current task in progress on this object, if it exists.

<a id="revision-model-ref"></a>

## `Revision`

Every time a page is edited, a new `Revision` is created and saved to the database. It can be used to find the full history of all changes that have been made to a page and it also provides a place for new changes to be kept before going live.

- Revisions can be created from any instance of [`RevisionMixin`](#wagtail.models.RevisionMixin) by calling its [`save_revision()`](#wagtail.models.RevisionMixin.save_revision) method.
- The content of the page is JSON-serialisable and stored in the [`content`](#wagtail.models.Revision.content) field.
- You can retrieve a `Revision` as an instance of the object’s model by calling the [`as_object()`](#wagtail.models.Revision.as_object) method.

You can use the [`purge_revisions`](management_commands.md#purge-revisions) command to delete old revisions that are no longer in use.

### Database fields

### *class* wagtail.models.Revision

#### content_object

(generic foreign key)

The object this revision belongs to. For page revisions, the object is an instance of the specific class.

#### content_type

(foreign key to [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType))

The content type of the object this revision belongs to. For page revisions, this means the content type of the specific page type.

#### base_content_type

(foreign key to [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType))

The base content type of the object this revision belongs to. For page revisions, this means the content type of the [`Page`](#wagtail.models.Page) model.

#### object_id

(string)

The primary key of the object this revision belongs to.

#### created_at

(date/time)

The time the revision was created.

#### user

(foreign key to user model)

The user that created the revision.

#### content

(dict)

The JSON content for the object at the time the revision was created.

### Managers

### *class* wagtail.models.Revision

#### objects

This default manager is used to retrieve all of the `Revision` objects in the database. It also provides a `wagtail.models.RevisionsManager.for_instance` method that lets you query for revisions of a specific object.

Example:

```python
Revision.objects.all()
Revision.objects.for_instance(my_object)
```

#### page_revisions

This manager extends the default manager and is used to retrieve all of the `Revision` objects that belong to pages.

Example:

```python
Revision.page_revisions.all()
```

### Methods and properties

### *class* wagtail.models.Revision

#### as_object()

This method retrieves this revision as an instance of its object’s specific class. If the revision belongs to a page, it will be an instance of the [`Page`](#wagtail.models.Page)’s specific subclass.

#### is_latest_revision()

Returns `True` if this revision is the object’s latest revision.

#### publish(user=None, changed=True, log_action=True, previous_revision=None, skip_permission_checks=False)

Calling this will copy the content of this revision into the live object. If the object is in draft, it will be published.

#### base_content_object

This property returns the object this revision belongs to as an instance of the base class.

## `GroupPagePermission`

### Database fields

### *class* wagtail.models.GroupPagePermission

#### group

(foreign key to `django.contrib.auth.models.Group`)

#### page

(foreign key to [`Page`](#wagtail.models.Page))

## `PageViewRestriction`

### Database fields

### *class* wagtail.models.PageViewRestriction

#### page

(foreign key to [`Page`](#wagtail.models.Page))

#### password

(text)

#### restriction_type

(text)

Options: none, password, groups, login

## `Orderable` (abstract)

### Database fields

### *class* wagtail.models.Orderable

#### sort_order

(number)

#### sort_order_field *= 'sort_order'*

## `Workflow`

Workflows represent sequences of tasks that must be approved for an action to be performed on an object - typically publication.

### Database fields

### *class* wagtail.models.Workflow

#### name

(text)

Human-readable name of the workflow.

#### active

(boolean)

Whether or not the workflow is active. Active workflows can be added to pages and snippets, and started. Inactive workflows cannot.

### Methods and properties

### *class* wagtail.models.Workflow

#### start(obj, user)

Initiates a workflow by creating an instance of `WorkflowState`.

#### tasks

Returns all `Task` instances linked to this workflow.

#### deactivate(user=None)

Sets the workflow as inactive, and cancels all in progress instances of `WorkflowState` linked to this workflow.

#### all_pages()

Returns a queryset of all the pages that this Workflow applies to.

## `WorkflowState`

Workflow states represent the status of a started workflow on an object.

### Database fields

### *class* wagtail.models.WorkflowState

#### content_object

(generic foreign key)

The object on which the workflow has been started. For page workflows, the object is an instance of the base `Page` model.

#### content_type

(foreign key to [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType))

The content type of the object this workflow state belongs to. For page workflows, this means the content type of the specific page type.

#### base_content_type

(foreign key to [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType))

The base content type of the object this workflow state belongs to. For page workflows, this means the content type of the [`Page`](#wagtail.models.Page) model.

#### object_id

(string)

The primary key of the object this revision belongs to.

#### workflow

(foreign key to `Workflow`)

The workflow whose state the `WorkflowState` represents.

#### status

(text)

The current status of the workflow (options are `WorkflowState.STATUS_CHOICES`)

#### created_at

(date/time)

When this instance of `WorkflowState` was created - when the workflow was started

#### requested_by

(foreign key to user model)

The user who started this workflow

#### current_task_state

(foreign key to `TaskState`)

The `TaskState` model for the task the workflow is currently at: either completing (if in progress) or the final task state (if finished)

### Methods and properties

### *class* wagtail.models.WorkflowState

#### STATUS_CHOICES

A tuple of the possible options for the `status` field, and their verbose names. Options are `STATUS_IN_PROGRESS`, `STATUS_APPROVED`,
`STATUS_CANCELLED` and `STATUS_NEEDS_CHANGES`.

#### update(user=None, next_task=None)

Checks the status of the current task, and progresses (or ends) the workflow if appropriate.
If the workflow progresses, next_task will be used to start a specific task next if provided.

#### get_next_task()

Returns the next active task, which has not been either approved or skipped.

#### cancel(user=None)

Cancels the workflow state

#### finish(user=None)

Finishes a successful in progress workflow, marking it as approved and performing the `on_finish` action.

#### resume(user=None)

Put a STATUS_NEEDS_CHANGES workflow state back into STATUS_IN_PROGRESS, and restart the current task

#### copy_approved_task_states_to_revision(revision)

Creates copies of previously approved task states with revision set to a different revision.

#### all_tasks_with_status()

Returns a list of Task objects that are linked with this workflow state’s
workflow. The status of that task in this workflow state is annotated in the
`.status` field. And a displayable version of that status is annotated in the
`.status_display` field.

This is different to querying TaskState as it also returns tasks that haven’t
been started yet (so won’t have a TaskState).

#### revisions()

Returns all revisions associated with task states linked to the current workflow state.

## `Task`

Tasks represent stages in a workflow that must be approved for the workflow to complete successfully.

### Database fields

### *class* wagtail.models.Task

#### name

(text)

Human-readable name of the task.

#### active

(boolean)

Whether or not the task is active: active workflows can be added to workflows, and started. Inactive workflows cannot, and are skipped when in
an existing workflow.

#### content_type

(foreign key to `django.contrib.contenttypes.models.ContentType`)

A foreign key to the [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType) object that represents the specific model of this task.

### Methods and properties

### *class* wagtail.models.Task

#### workflows

Returns all `Workflow` instances that use this task.

#### active_workflows

Return a `QuerySet`` of active workflows that this task is part of.

#### task_state_class

The specific task state class to generate to store state information for this task. If not specified, this will be `TaskState`.

#### *classmethod* get_verbose_name()

Returns the human-readable “verbose name” of this task model e.g “Group approval task”.

#### specific

Returns this object in its most specific subclassed form with all field
values fetched from the database. The result is cached in memory.

#### start(workflow_state, user=None)

Start this task on the provided workflow state by creating an instance of TaskState.

#### on_action(task_state, user, action_name, \*\*kwargs)

Performs an action on a task state determined by the `action_name` string passed.

#### user_can_access_editor(obj, user)

Returns `True` if a user who would not normally be able to access the editor for the
object should be able to if the object is currently on this task.
Note that returning `False` does not remove permissions from users who would otherwise have them.

#### user_can_lock(obj, user)

Returns `True` if a user who would not normally be able to lock the object should be able to
if the object is currently on this task.
Note that returning `False` does not remove permissions from users who would otherwise have them.

#### user_can_unlock(obj, user)

Returns `True` if a user who would not normally be able to unlock the object should be able to
if the object is currently on this task.
Note that returning `False` does not remove permissions from users who would otherwise have them.

#### locked_for_user(obj, user)

Returns `True` if the object should be locked to a given user’s edits.
This can be used to prevent editing by non-reviewers.

#### get_actions(obj, user)

Get the list of action strings (name, verbose_name, whether the action requires additional data - see
`get_form_for_action`) for actions the current user can perform for this task on the given object.
These strings should be the same as those able to be passed to `on_action`.

#### get_task_states_user_can_moderate(user, \*\*kwargs)

Returns a `QuerySet` of the task states the current user can moderate

#### deactivate(user=None)

Set `active` to False and cancel all in progress task states linked to this task.

#### get_form_for_action(action)

#### get_template_for_action(action)

Specifies a template for the workflow action modal.

#### *classmethod* get_description()

Returns the task description.

## `TaskState`

Task states store state information about the progress of a task on a particular revision.

### Database fields

### *class* wagtail.models.TaskState

#### workflow_state

(foreign key to [`WorkflowState`](#wagtail.models.WorkflowState))

The workflow state which started this task state.

#### revision

(foreign key to [`Revision`](#wagtail.models.Revision))

The revision this task state was created on.

#### task

(foreign key to [`Task`](#wagtail.models.Task))

The task that this task state is storing state information for.

#### status

(text)

The completion status of the task on this revision. Options are available in `TaskState.STATUS_CHOICES`)

#### content_type

(foreign key to `django.contrib.contenttypes.models.ContentType`)

A foreign key to the [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType) object that represents the specific model of this task.

#### started_at

(date/time)

When this task state was created.

#### finished_at

(date/time)

When this task state was canceled, rejected, or approved.

#### finished_by

(foreign key to user model)

The user who completed (canceled, rejected, approved) the task.

#### comment

(text)

A text comment is typically added by a user when the task is completed.

### Methods and properties

### *class* wagtail.models.TaskState

#### STATUS_CHOICES

A tuple of the possible options for the `status` field, and their verbose names. Options are `STATUS_IN_PROGRESS`, `STATUS_APPROVED`,
`STATUS_CANCELLED`, `STATUS_REJECTED` and `STATUS_SKIPPED`.

#### exclude_fields_in_copy

A list of fields not to copy when the `TaskState.copy()` method is called.

#### specific

Returns this object in its most specific subclassed form with all field
values fetched from the database. The result is cached in memory.

#### approve(user=None, update=True, comment='')

Approve the task state and update the workflow state.

#### reject(user=None, update=True, comment='')

Reject the task state and update the workflow state.

#### task_type_started_at

Finds the first chronological started_at for successive TaskStates - ie started_at if the task had not been restarted.

#### cancel(user=None, resume=False, comment='')

Cancel the task state and update the workflow state.
If `resume` is set to True, then upon update the workflow state is passed the current task as `next_task`,
causing it to start a new task state on the current task if possible.

#### copy(update_attrs=None, exclude_fields=None)

Copy this task state, excluding the attributes in the `exclude_fields` list and updating any attributes
to values specified in the `update_attrs` dictionary of `attribute`: `new value` pairs.

#### get_comment()

Returns a string that is displayed in workflow history.

This could be a comment by the reviewer, or generated.
Use mark_safe to return HTML.

## `WorkflowTask`

Represents the ordering of a task in a specific workflow.

### Database fields

### *class* wagtail.models.WorkflowTask

#### workflow

(foreign key to `Workflow`)

#### task

(foreign key to `Task`)

#### sort_order

(number)

The ordering of the task in the workflow.

## `WorkflowPage`

Represents the assignment of a workflow to a page and its descendants.

### Database fields

### *class* wagtail.models.WorkflowPage

#### workflow

(foreign key to [`Workflow`](#wagtail.models.Workflow))

#### page

(foreign key to [`Page`](#wagtail.models.Page))

## `WorkflowContentType`

Represents the assignment of a workflow to a Django model.

### Database fields

### *class* wagtail.models.WorkflowContentType

#### workflow

(foreign key to [`Workflow`](#wagtail.models.Workflow))

#### content_type

(foreign key to [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType))

A foreign key to the `ContentType` object that represents the model that is assigned to the workflow.

## `BaseLogEntry`

An abstract base class that represents a record of an action performed on an object.

### Database fields

### *class* wagtail.models.BaseLogEntry

#### content_type

(foreign key to `django.contrib.contenttypes.models.ContentType`)

A foreign key to the [`ContentType`](https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType) object that represents the specific model of this model.

#### label

(text)

The object title at the time of the entry creation

Note: Wagtail will attempt to use `get_admin_display_title` or the string representation of the object passed to `LogEntryManager.log_action`

#### user

(foreign key to user model)

A foreign key to the user that triggered the action.

#### revision

(foreign key to [`Revision`](#wagtail.models.Revision))

A foreign key to the current revision.

#### data

(dict)

The JSON representation of any additional details for each action.
For example, source page id and title when copying from a page. Or workflow id/name and next step id/name on a workflow transition

#### timestamp

(date/time)

The date/time when the entry was created.

#### content_changed

(boolean)

A boolean that can be set to `True` when the content has changed.

#### deleted

(boolean)

A boolean that can set to `True` when the object is deleted. Used to filter entries in the Site History report.

### Methods and properties

### *class* wagtail.models.BaseLogEntry

#### user_display_name

Returns the display name of the associated user;
get_full_name if available and non-empty, otherwise get_username.
Defaults to ‘system’ when none is provided

#### comment

#### object_verbose_name

#### object_id()

## `PageLogEntry`

Represents a record of an action performed on an [`Page`](#wagtail.models.Page), subclasses [`BaseLogEntry`](#wagtail.models.BaseLogEntry).

### Database fields

### *class* wagtail.models.PageLogEntry

#### page

(foreign key to [`Page`](#wagtail.models.Page))

A foreign key to the page the action is performed on.

## `Comment`

Represents a comment on a page.

### Database fields

### *class* wagtail.models.Comment

#### page

(parental key to [`Page`](#wagtail.models.Page))

A parental key to the page the comment has been added to.

#### user

(foreign key to user model)

A foreign key to the user who added this comment.

#### text

(text)

The text content of the comment.

#### contentpath

(text)

The path to the field or streamfield block the comment is attached to,
in the form `field` or `field.streamfield_block_id`.

#### position

(text)

An identifier for the position of the comment within its field. The format
used is determined by the field.

#### created_at

(date/time)

The date/time when the comment was created.

#### updated_at

(date/time)

The date/time when the comment was updated.

#### revision_created

(foreign key to [`Revision`](#wagtail.models.Revision))

A foreign key to the revision on which the comment was created.

#### resolved_at

(date/time)

The date/time when the comment was resolved, if any.

#### resolved_by

(foreign key to user model)

A foreign key to the user who resolved this comment, if any.

## `CommentReply`

Represents a reply to a comment thread.

### Database fields

### *class* wagtail.models.CommentReply

#### comment

(parental key to [`Comment`](#wagtail.models.Comment))

A parental key to the comment that started the thread.

#### user

(foreign key to user model)

A foreign key to the user who added this comment.

#### text

(text)

The text content of the comment.

#### created_at

(date/time)

The date/time when the comment was created.

#### updated_at

(date/time)

The date/time when the comment was updated.

## `PageSubscription`

Represents a user’s subscription to email notifications about page events.
Currently only used for comment notifications.

### Database fields

### *class* wagtail.models.PageSubscription

#### page

(parental key to [`Page`](#wagtail.models.Page))

#### user

(foreign key to user model)

#### comment_notifications

(boolean)

Whether the user should receive comment notifications for all comments,
or just comments in threads they participate in.
