Improve grammar, spelling, and punctuation in Extending Wagtail section (#9373)

pull/9435/head
Albina 2022-10-19 22:41:50 +02:00 zatwierdzone przez GitHub
rodzic 86437515a3
commit 4f478a514b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
9 zmienionych plików z 42 dodań i 42 usunięć

Wyświetl plik

@ -1,12 +1,12 @@
# Creating admin views
The most common use for adding custom views to the Wagtail admin is to provide an interface for managing a Django model. The [Index](../reference/contrib/modeladmin/index) app makes this simple, providing ready-made views for listing, creating and editing objects with minimal configuration.
The most common use for adding custom views to the Wagtail admin is to provide an interface for managing a Django model. The [Index](../reference/contrib/modeladmin/index) app makes this simple, providing ready-made views for listing, creating, and editing objects with minimal configuration.
For other kinds of admin view that don't fit this pattern, you can write your own Django views and register them as part of the Wagtail admin through [hooks](admin_hooks). In this example, we'll implement a view that displays a calendar for the current year, using [the calendar module](https://docs.python.org/3/library/calendar.html) from Python's standard library.
For other kinds of admin views that don't fit this pattern, you can write your own Django views and register them as part of the Wagtail admin through [hooks](admin_hooks). In this example, we'll implement a view that displays a calendar for the current year, using [the calendar module](https://docs.python.org/3/library/calendar.html) from Python's standard library.
## Defining a view
Within a Wagtail project, create a new `wagtailcalendar` app with `./manage.py startapp wagtailcalendar` and add it to your project's `INSTALLED_APPS`. (In this case we're using the name 'wagtailcalendar' to avoid clashing with the standard library's `calendar` module - in general there is no need to use a 'wagtail' prefix.)
Within a Wagtail project, create a new `wagtailcalendar` app with `./manage.py startapp wagtailcalendar` and add it to your project's `INSTALLED_APPS`. (In this case, we're using the name 'wagtailcalendar' to avoid clashing with the standard library's `calendar` module - in general, there is no need to use a 'wagtail' prefix.)
Edit `views.py` as follows - note that this is a plain Django view with no Wagtail-specific code.
@ -26,9 +26,9 @@ def index(request):
## Registering a URL route
At this point, the standard practice for a Django project would be to add a URL route for this view to your project's top-level URL config module. However, in this case we want the view to only be available to logged-in users, and to appear within the `/admin/` URL namespace which is managed by Wagtail. This is done through the [Register Admin URLs](register_admin_urls) hook.
At this point, the standard practice for a Django project would be to add a URL route for this view to your project's top-level URL config module. However, in this case, we want the view to only be available to logged-in users, and to appear within the `/admin/` URL namespace which is managed by Wagtail. This is done through the [Register Admin URLs](register_admin_urls) hook.
On startup, Wagtail looks for a `wagtail_hooks` submodule within each installed app. In this submodule, you can define functions to be run at various points in Wagtail's operation, such as building the URL config for the admin, and constructing the main menu.
On startup, Wagtail looks for a `wagtail_hooks` submodule within each installed app. In this submodule, you can define functions to be run at various points in Wagtail's operation, such as building the URL config for the admin and constructing the main menu.
Create a `wagtail_hooks.py` file within the `wagtailcalendar` app containing the following:
@ -52,10 +52,10 @@ The calendar will now be visible at the URL `/admin/calendar/`.
## Adding a template
Currently this view is outputting a plain HTML fragment. Let's insert this into the usual Wagtail admin page furniture, by creating a template that extends Wagtail's base template `"wagtailadmin/base.html"`.
Currently, this view is outputting a plain HTML fragment. Let's insert this into the usual Wagtail admin page furniture, by creating a template that extends Wagtail's base template `"wagtailadmin/base.html"`.
```{note}
The base template and HTML structure are not considered astable part of Wagtail's API, and may change in futurereleases.
The base template and HTML structure are not considered a stable part of Wagtail's API and may change in future releases.
```
Update `views.py` as follows:
@ -139,7 +139,7 @@ A 'Calendar' item will now appear in the menu.
## Adding a group of menu items
Sometimes you want to group custom views together in a single menu item in the sidebar. Let's create another view to display only the current calendar month:
Sometimes you want to group custom views in a single menu item in the sidebar. Let's create another view to display only the current calendar month:
```{code-block} python
:emphasize-lines: 15-23

Wyświetl plik

@ -2,12 +2,12 @@
# Audit log
Wagtail provides a mechanism to log actions performed on its objects. Common activities such as page creation, update, deletion, locking and unlocking, revision scheduling and privacy changes are automatically logged at the model level.
Wagtail provides a mechanism to log actions performed on its objects. Common activities such as page creation, update, deletion, locking and unlocking, revision scheduling, and privacy changes are automatically logged at the model level.
The Wagtail admin uses the action log entries to provide a site-wide and page specific history of changes. It uses a
The Wagtail admin uses the action log entries to provide a site-wide and page-specific history of changes. It uses a
registry of 'actions' that provide additional context for the logged action.
The audit log-driven Page history replaces the revisions list page, but provide a filter for revision-specific entries.
The audit log-driven Page history replaces the revisions list page, but provides a filter for revision-specific entries.
```{note}
The audit log does not replace revisions.
@ -24,12 +24,12 @@ The `wagtail.log_actions.log` function can be used to add logging to your own co
:param action: The code name for the action being performed. This can be one of the names listed below, or a custom action defined through the :ref:`register_log_actions` hook.
:param user: Optional - the user initiating the action. For actions logged within an admin view, this defaults to the logged-in user.
:param uuid: Optional - log entries given the same UUID indicates that they occurred as part of the same user action (for example a page being immediately published on creation).
:param title: The string representation of the instance being logged. By default, Wagtail will attempt to use the instance's ``str`` representation, or ``get_admin_display_title`` for page objects.
:param title: The string representation, of the instance being logged. By default, Wagtail will attempt to use the instance's ``str`` representation or ``get_admin_display_title`` for page objects.
:param data: Optional - a dictionary of additional JSON-serialisable data to store against the log entry
```
```{note}
When adding logging, you need to log the action or actions that happen to the object. For example, if the user creates and publishes a page, there should be a "create" entry and a "publish" entry. Or, if the user copies a published page and chooses to keep it published, there should be a "copy" and a "publish" entry for new page.
When adding logging, you need to log the action or actions that happen to the object. For example, if the user creates and publishes a page, there should be a "create" entry and a "publish" entry. Or, if the user copies a published page and chooses to keep it published, there should be a "copy" and a "publish" entry for the new page.
```
```python
@ -61,10 +61,10 @@ The `log` function was added. Previously, logging was only implemented for pages
| Action | Notes |
| --------------------------------- | -------------------------------------------------------------------------------- |
| `wagtail.create` | The object was created |
| `wagtail.edit` | The object was edited (for pages, saved as draft) |
| `wagtail.edit` | The object was edited (for pages, saved as a draft) |
| `wagtail.delete` | The object was deleted. Will only surface in the Site History for administrators |
| `wagtail.publish` | The page was published |
| `wagtail.publish.schedule` | Draft is scheduled for publishing |
| `wagtail.publish.schedule` | The draft is scheduled for publishing |
| `wagtail.publish.scheduled` | Draft published via `publish_scheduled` management command |
| `wagtail.schedule.cancel` | Draft scheduled for publishing cancelled via "Cancel scheduled publish" |
| `wagtail.unpublish` | The page was unpublished |
@ -78,13 +78,13 @@ The `log` function was added. Previously, logging was only implemented for pages
| `wagtail.copy` | The page was copied to a new location |
| `wagtail.copy_for_translation` | The page was copied into a new locale for translation |
| `wagtail.move` | The page was moved to a new location |
| `wagtail.reorder` | The order of the page under it's parent was changed |
| `wagtail.reorder` | The order of the page under its parent was changed |
| `wagtail.view_restriction.create` | The page was restricted |
| `wagtail.view_restriction.edit` | The page restrictions were updated |
| `wagtail.view_restriction.delete` | The page restrictions were removed |
| `wagtail.workflow.start` | The page was submitted for moderation in a Workflow |
| `wagtail.workflow.approve` | The draft was approved at a Workflow Task |
| `wagtail.workflow.reject` | The draft was rejected, and changes requested at a Workflow Task |
| `wagtail.workflow.reject` | The draft was rejected, and changes were requested at a Workflow Task |
| `wagtail.workflow.resume` | The draft was resubmitted to the workflow |
| `wagtail.workflow.cancel` | The workflow was cancelled |

Wyświetl plik

@ -34,9 +34,9 @@ The attributes are as follows:
- `template_name` - The path to the confirmation template
- `models` - A list of models on which the bulk action can act
- `action_priority` (optional) - A number that is used to determine the placement of the button in the list of buttons
- `classes` (optional) - A set of CSS classnames that will be used on the button in the user interface
- `classes` (optional) - A set of CSS class names that will be used on the button in the user interface
An example for a confirmation template is as follows:
An example of a confirmation template is as follows:
```html+django
<!-- /path/to/confirm_bulk_delete.html -->

Wyświetl plik

@ -2,13 +2,13 @@
The Workflow system allows users to create tasks, which represent stages of moderation.
Wagtail provides one built in task type: `GroupApprovalTask`, which allows any user in specific groups to approve or reject moderation.
Wagtail provides one built-in task type: `GroupApprovalTask`, which allows any user in specific groups to approve or reject moderation.
However, it is possible to add your own task types in code. Instances of your custom task can then be created in the `Tasks` section of the Wagtail Admin.
However, it is possible to implement your own task types. Instances of your custom task can then be created in the `Tasks` section of the Wagtail Admin.
## Task models
All custom tasks must be models inheriting from `wagtailcore.Task`. In this set of examples, we'll set up a task which can be approved by only one specific user.
All custom tasks must be models inheriting from `wagtailcore.Task`. In this set of examples, we'll set up a task that can be approved by only one specific user.
```python
# <project>/models.py
@ -122,11 +122,11 @@ class UserApprovalTask(Task):
## Customising behaviour
Both `Task` and `TaskState` have a number of methods which can be overridden to implement custom behaviour. Here are some of the most useful:
Both `Task` and `TaskState` have a number of methods that can be overridden to implement custom behaviour. Here are some of the most useful:
`Task.user_can_access_editor(page, user)`, `Task.user_can_lock(page, user)`, `Task.user_can_unlock(page, user)`:
These methods determine if users usually without permissions can access the editor, lock, or unlock the page, by returning True or False.
These methods determine if users usually without permission can access the editor, and lock, or unlock the page, by returning True or False.
Note that returning `False` will not prevent users who would normally be able to perform those actions. For example, for our `UserApprovalTask`:
```python
@ -172,7 +172,7 @@ Returns the name of a custom template to be used in rendering the data entry mod
`Task.on_action(task_state, user, action_name, **kwargs)`:
This performs the actions specified in `Task.get_actions(page, user)`: it is passed an action name, for example `approve`, and the relevant task state. By default, it calls `approve` and `reject` methods on the task state when the corresponding action names are passed through. Any additional data entered in a modal (see `get_form_for_action` and `get_actions`) is supplied as kwargs.
This performs the actions specified in `Task.get_actions(page, user)`: it is passed an action name, for example, `approve`, and the relevant task state. By default, it calls `approve` and `reject` methods on the task state when the corresponding action names are passed through. Any additional data entered in a modal (see `get_form_for_action` and `get_actions`) is supplied as kwargs.
For example, let's say we wanted to add an additional option: cancelling the entire workflow:
@ -265,7 +265,7 @@ class UserApprovalTaskStateSubmissionEmailNotifier(BaseUserApprovalTaskStateEmai
Similarly, you could define notifier subclasses for approval and rejection notifications.
Next, you need to instantiate the notifier, and connect it to the `task_submitted` signal.
Next, you need to instantiate the notifier and connect it to the `task_submitted` signal.
```python
# <project>/signal_handlers.py

Wyświetl plik

@ -86,7 +86,7 @@ Add the field to the group 'edit'/'create' templates:
{% endblock extra_fields %}
```
Finally we configure the `wagtail.users` application to use the custom viewset, by setting up a custom `AppConfig` class. Within your project folder (which will be the package containing the top-level settings and urls modules), create `apps.py` (if it does not exist already) and add:
Finally, we configure the `wagtail.users` application to use the custom viewset, by setting up a custom `AppConfig` class. Within your project folder (which will be the package containing the top-level settings and urls modules), create `apps.py` (if it does not exist already) and add:
```python
from wagtail.users.apps import WagtailUsersAppConfig

Wyświetl plik

@ -4,9 +4,9 @@ Wagtails rich text editor is built with [Draftail](https://www.draftail.org/)
Plugins come in three types:
- Inline styles – To format a portion of a line, for example `bold`, `italic`, `monospace`.
- Blocks – To indicate the structure of the content, for example `blockquote`, `ol`.
- Entities – To enter additional data/metadata, for example `link` (with a URL), `image` (with a file).
- Inline styles – To format a portion of a line, for example `bold`, `italic` or `monospace`.
- Blocks – To indicate the structure of the content, for example, `blockquote`, `ol`.
- Entities – To enter additional data/metadata, for example, `link` (with a URL) or `image` (with a file).
All of these plugins are created with a similar baseline, which we can demonstrate with one of the simplest examples – a custom feature for an inline style of `mark`. Place the following in a `wagtail_hooks.py` file in any installed app:
@ -134,13 +134,13 @@ But in the meantime, consider implementing your UI through [StreamField](../topi
Here are the main requirements to create a new entity feature:
- Like for inline styles and blocks, register an editor plugin.
- As for inline styles and blocks, register an editor plugin.
- The editor plugin must define a `source`: a React component responsible for creating new entity instances in the editor, using the Draft.js API.
- The editor plugin also needs a `decorator` (for inline entities) or `block` (for block entities): a React component responsible for displaying entity instances within the editor.
- Like for inline styles and blocks, set up the to/from DB conversion.
- The conversion usually is more involved, since entities contain data that needs to be serialised to HTML.
To write the React components, Wagtail exposes its own React, Draft.js and Draftail dependencies as global variables. Read more about this in [ectending clientside components](extending_clientside_components).
To write the React components, Wagtail exposes its own React, Draft.js, and Draftail dependencies as global variables. Read more about this in [ectending clientside components](extending_clientside_components).
To go further, please look at the [Draftail documentation](https://www.draftail.org/docs/formatting-options) as well as the [Draft.js exporter documentation](https://github.com/springload/draftjs_exporter).
Here is a detailed example to showcase how those tools are used in the context of Wagtail.
@ -191,7 +191,7 @@ def register_stock_feature(features):
The `js` and `css` keyword arguments on `EntityFeature` can be used to specify additional JS and CSS files to load when this feature is active. Both are optional. Their values are added to a `Media` object, more documentation on these objects is available in the [Django Form Assets documentation](django:topics/forms/media).
Since entities hold data, the conversion to/from database format is more complicated. We have to create the two handlers:
Since entities hold data, the conversion to/from database format is more complicated. We have to create two handlers:
```python
from draftjs_exporter.dom import DOM
@ -342,5 +342,5 @@ Custom block entities can also be created (have a look at the separate [Draftail
To further customise how the Draftail widgets are integrated into the UI, there are additional extension points for CSS and JS:
- In JavaScript, use the `[data-draftail-input]` attribute selector to target the input which contains the data, and `[data-draftail-editor-wrapper]` for the element which wraps the editor.
- The editor instance is bound on the input field for imperative access. Use `document.querySelector('[data-draftail-input]').draftailEditor`.
- The editor instance is bound to the input field for imperative access. Use `document.querySelector('[data-draftail-input]').draftailEditor`.
- In CSS, use the classes prefixed with `Draftail-`.

Wyświetl plik

@ -1,6 +1,6 @@
# Using forms in admin views
[Django's forms framework](https://docs.djangoproject.com/en/stable/topics/forms/) can be used within Wagtail admin views just like in any other Django app. However, Wagtail also provides various admin-specific form widgets, such as date/time pickers and choosers for pages, documents, images and snippets. By constructing forms using `wagtail.admin.forms.models.WagtailAdminModelForm` as the base class instead of `django.forms.models.ModelForm`, the most appropriate widget will be selected for each model field. For example, given the model and form definition:
[Django's forms framework](https://docs.djangoproject.com/en/stable/topics/forms/) can be used within Wagtail admin views just like in any other Django app. However, Wagtail also provides various admin-specific form widgets, such as date/time pickers and choosers for pages, documents, images, and snippets. By constructing forms using `wagtail.admin.forms.models.WagtailAdminModelForm` as the base class instead of `django.forms.models.ModelForm`, the most appropriate widget will be selected for each model field. For example, given the model and form definition:
```python
from django.db import models

Wyświetl plik

@ -1,10 +1,10 @@
# Generic views
Wagtail provides a number of generic views for handling common tasks such as creating / editing model instances, and chooser modals. Since these often involve several related views with shared properties (such as the model that we're working with, and its associated icon) Wagtail also implements the concept of a _viewset_, which allows a bundle of views to be defined collectively, and their URLs to be registered with the admin app as a single operation through the `register_admin_viewset` hook.
Wagtail provides several generic views for handling common tasks such as creating / editing model instances and chooser modals. Since these often involve several related views with shared properties (such as the model that we're working with, and its associated icon) Wagtail also implements the concept of a _viewset_, which allows a bundle of views to be defined collectively, and their URLs to be registered with the admin app as a single operation through the `register_admin_viewset` hook.
## ModelViewSet
The `wagtail.admin.viewsets.model.ModelViewSet` class provides the views for listing, creating, editing and deleting model instances. For example, if we have the following model:
The `wagtail.admin.viewsets.model.ModelViewSet` class provides the views for listing, creating, editing, and deleting model instances. For example, if we have the following model:
```python
from django.db import models
@ -116,7 +116,7 @@ Within `wagtail.admin.views.generic.chooser`:
Within `wagtail.admin.widgets`:
- `BaseChooser.get_instance(value)` - given a value that may be a record, a primary key or None, returns the corresponding record or None
- `BaseChooser.get_instance(value)` - given a value that may be a record, a primary key, or None, returns the corresponding record or None
- `BaseChooser.get_value_data_from_instance(item)` - given a record, returns the dictionary of data that will populate the chooser widget (consisting of items `id` and `title`, unless the widget's JavaScript has been customised)
For example, the following code will implement a chooser that runs against a JSON endpoint for the User model at `http://localhost:8000/api/users/`, set up with Django REST Framework using the default configuration and no pagination:

Wyświetl plik

@ -178,7 +178,7 @@ def register_external_link(features):
features.register_link_type(NoFollowExternalLinkHandler)
```
Similarly you can use `email` linktype to add a custom rewrite handler for email links (for example to obfuscate emails in rich text).
Similarly, you can use `email` linktype to add a custom rewrite handler for email links (for example to obfuscate emails in rich text).
```{eval-rst}
.. method:: FeatureRegistry.register_embed_type(handler)
@ -241,7 +241,7 @@ class CustomRichTextArea(widgets.TextArea):
```{eval-rst}
.. method:: FeatureRegistry.register_editor_plugin(editor_name, feature_name, plugin_definition)
Rich text editors often provide a plugin mechanism to allow extending the editor with new functionality. The ``register_editor_plugin`` method provides a standardised way for ``register_rich_text_features`` hooks to define plugins to be pulled in to the editor when a given rich text feature is enabled.
Rich text editors often provide a plugin mechanism to allow extending the editor with new functionality. The ``register_editor_plugin`` method provides a standardised way for ``register_rich_text_features`` hooks to define plugins to be pulled into the editor when a given rich text feature is enabled.
``register_editor_plugin`` is passed an editor name (a string uniquely identifying the editor widget - Wagtail uses the identifier ``draftail`` for the built-in editor), a feature identifier, and a plugin definition object. This object is specific to the editor widget and can be any arbitrary value, but will typically include a :doc:`Django form media <django:topics/forms/media>` definition referencing the plugin's JavaScript code - which will then be merged into the editor widget's own media definition - along with any relevant configuration options to be passed when instantiating the editor.
@ -258,9 +258,9 @@ For details of the plugin formats for Wagtail's built-in editors, see :doc:`./ex
Editor widgets will often be unable to work directly with Wagtail's rich text format, and require conversion to their own native format. For Draftail, this is a JSON-based format known as ContentState (see [How Draft.js Represents Rich Text Data](https://rajaraodv.medium.com/how-draft-js-represents-rich-text-data-eeabb5f25cf2)). Editors based on HTML's `contentEditable` mechanism require valid HTML, and so Wagtail uses a convention referred to as "editor HTML", where the additional data required on link and embed elements is stored in `data-` attributes, for example: `<a href="/contact-us/" data-linktype="page" data-id="3">Contact us</a>`.
Wagtail provides two utility classes, `wagtail.admin.rich_text.converters.contentstate.ContentstateConverter` and `wagtail.admin.rich_text.converters.editor_html.EditorHTMLConverter`, to perform conversions between rich text format and the native editor formats. These classes are independent of any editor widget, and distinct from the rewriting process that happens when rendering rich text onto a template.
Wagtail provides two utility classes, `wagtail.admin.rich_text.converters.contentstate.ContentstateConverter` and `wagtail.admin.rich_text.converters.editor_html.EditorHTMLConverter`, to perform conversions between rich text format and the native editor formats. These classes are independent of any editor widget and distinct from the rewriting process that happens when rendering rich text onto a template.
Both classes accept a `features` list as an argument to their constructor, and implement two methods, `from_database_format(data)` which converts Wagtail rich text data to the editor's format, and `to_database_format(data)` which converts editor data to Wagtail rich text format.
Both classes accept a `features` list as an argument to their constructor and implement two methods, `from_database_format(data)` which converts Wagtail rich text data to the editor's format, and `to_database_format(data)` which converts editor data to Wagtail rich text format.
As with editor plugins, the behaviour of a converter class can vary according to the feature list passed to it. In particular, it can apply whitelisting rules to ensure that the output only contains HTML elements corresponding to the currently active feature set. The feature registry provides a `register_converter_rule` method to allow `register_rich_text_features` hooks to define conversion rules that will be activated when a given feature is enabled.