diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1851af9308..6c3f9c649a 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -19,6 +19,7 @@ Changelog * Fix: Use the latest draft when copying an unpublished page for translation (Andrey Nehaychik) * Fix: Make Workflow and Aging Pages reports only available to users with page-related permissions (Rohit Sharma) * Docs: Document, for contributors, the use of translate string literals passed as arguments to tags and filters using `_()` within templates (Chiemezuo Akujobi) + * Docs: Document all features for the Documents app in one location (Neeraj Yetheendran) * Maintenance: Update BeautifulSoup upper bound to 4.12.x (scott-8) * Maintenance: Migrate initialization of classes (such as `body.ready`) from multiple JavaScript implementations to one Stimulus controller `w-init` (Chiemezuo Akujobi) * Maintenance: Adopt the usage of of translate string literals using `arg=_('...')` in all `wagtailadmin` module templates (Chiemezuo Akujobi) diff --git a/docs/advanced_topics/deploying.md b/docs/advanced_topics/deploying.md index ae055d128f..185d3f9cca 100644 --- a/docs/advanced_topics/deploying.md +++ b/docs/advanced_topics/deploying.md @@ -24,6 +24,8 @@ See [Django's documentation on deploying static files](django:howto/static-files The JavaScript and CSS files used by the Wagtail admin frequently change between releases of Wagtail - it's important to avoid serving outdated versions of these files due to browser or server-side caching, as this can cause hard-to-diagnose issues. We recommend enabling [ManifestStaticFilesStorage](django.contrib.staticfiles.storage.ManifestStaticFilesStorage) in the `STATICFILES_STORAGE` setting - this ensures that different versions of files are assigned distinct URLs. +(user_uploaded_files)= + ### User Uploaded Files Wagtail follows [Django's conventions for managing uploaded files](django:topics/files). diff --git a/docs/advanced_topics/documents/custom_document_model.md b/docs/advanced_topics/documents/custom_document_model.md index c0f9f79c94..59b77cb191 100644 --- a/docs/advanced_topics/documents/custom_document_model.md +++ b/docs/advanced_topics/documents/custom_document_model.md @@ -1,5 +1,3 @@ -(custom_document_model)= - # Custom document model An alternate `Document` model can be used to add custom behaviour and diff --git a/docs/advanced_topics/documents/custom_document_upload_form.md b/docs/advanced_topics/documents/custom_document_upload_form.md new file mode 100644 index 0000000000..95fdabbd52 --- /dev/null +++ b/docs/advanced_topics/documents/custom_document_upload_form.md @@ -0,0 +1,35 @@ +# Custom document upload form + +Wagtail provides a way to use a custom document form by modifying the [`WAGTAILDOCS_DOCUMENT_FORM_BASE`](wagtaildocs_document_form_base) setting. This setting allows you to extend the default document form with your custom fields and logic. + +Here's an example: + +```python +# settings.py +WAGTAILDOCS_DOCUMENT_FORM_BASE = 'myapp.forms.CustomDocumentForm' +``` + +```python +# myapp/forms.py +from django import forms + +from wagtail.documents.forms import BaseDocumentForm + +class CustomDocumentForm(BaseDocumentForm): + terms_and_conditions = forms.BooleanField( + label="I confirm that this document was not created by AI.", + required=True, + ) + + def clean(self): + cleaned_data = super().clean() + if not cleaned_data.get("terms_and_conditions"): + raise forms.ValidationError( + "You must confirm the document was not created by AI." + ) + return cleaned_data +``` + +```{note} +Any custom document form should extend the built-in `BaseDocumentForm` class. +``` diff --git a/docs/advanced_topics/documents/index.md b/docs/advanced_topics/documents/index.md index 44d50111e7..aa5519ab90 100644 --- a/docs/advanced_topics/documents/index.md +++ b/docs/advanced_topics/documents/index.md @@ -4,6 +4,9 @@ --- maxdepth: 2 --- +overview custom_document_model +custom_document_upload_form +storing_and_serving title_generation_on_upload ``` diff --git a/docs/advanced_topics/documents/overview.md b/docs/advanced_topics/documents/overview.md new file mode 100644 index 0000000000..e3f4b8039d --- /dev/null +++ b/docs/advanced_topics/documents/overview.md @@ -0,0 +1,213 @@ +(overview)= + +# Documents overview + +This page provides an overview of the basics of using the `'wagtail.documents'` app in your Wagtail project. + +## Including `'wagtail.documents'` in `INSTALLED_APPS` + +To use the `wagtail.documents` app, you need to include it in the `INSTALLED_APPS` list in your Django project's settings. Simply add it to the list like this: + +```python +# settings.py + +INSTALLED_APPS = [ + # ... + 'wagtail.documents', + # ... +] +``` + +## Setting up URLs + +Next, you need to set up URLs for the `wagtail.documents` app. You can include these URLs in your project's main urls.py file. To do this, add the following lines: + +```python +# urls.py + +from wagtail.documents import urls as wagtaildocs_urls + +urlpatterns = [ + # ... + path('documents/', include(wagtaildocs_urls)), + # ... +] +``` + +New documents saved are stored in the [reference index](managing_the_reference_index) by default. + +## Using documents in a Page + +To include a document file in a Wagtail page, you can use `FieldPanel` in your page model. + +Here's an example: + +```python +# models.py + +from wagtail.admin.panels import FieldPanel +from wagtail.documents import get_document_model + + +class YourPage(Page): + # ... + document = models.ForeignKey( + get_document_model(), + null=True, + blank=True, + on_delete=models.SET_NULL, + ) + + content_panels = Page.content_panels + [ + # ... + FieldPanel('document'), + ] + +``` + +This allows you to select a document file when creating or editing a page, and link to it in your page template. + +Here's an example template to access the document field and render it: + +```html +{% extends "base.html" %} +{% block content %} + {% if page.document %} + <h2>Document: {{ page.document.title }}</h2> + <p>File Type: {{ page.document.file_extension }}</p> + <a href="{{ page.document.url }}" target="_blank">View Document</a> + {% else %} + <p>No document attached to this page.</p> + {% endif %} + <div>{{ page.body }}</div> +{% endblock %} +``` + +## Using documents within `RichTextFields` + +Links to documents can be made in pages using the [`RichTextField`](rich_text_docs). By default, Wagtail will include the features for adding links to documents see [](rich_text_features). + + +You can either exclude or include these by passing the `features` to your `RichTextField`. In the example below we create a `RichTextField` with only documents and basic formatting. + + +```python +# models.py +from wagtail.fields import RichTextField + +class BlogPage(Page): + # ...other fields + document_footnotes = RichTextField( + blank=True, + features=["bold", "italic", "ol", "document-link"] + ) + + panels = [ + # ...other panels + FieldPanel("document_footnotes"), + ] +``` + + + +## Using documents within `StreamField` + +`StreamField` provides a content editing model suitable for pages that do not follow a fixed structure. To add links to documents using `StreamField`, include it in your models and also include the `DocumentChooserBlock`. + +Create a `Page` model with a `StreamField` named `doc` and a `DocumentChooserBlock` named `doc_link` inside the field: + +```python +# models.py + +from wagtail.fields import StreamField +from wagtail.documents.blocks import DocumentChooserBlock + + +class BlogPage(Page): + # ... other fields + + documents = StreamField([ + ('document', DocumentChooserBlock()) + ], + null=True, + blank=True, + use_json_field=True, + ) + + panels = [ + # ... other panels + FieldPanel("documents"), + ] +``` + +In `blog_page.html`, add the following block of code to display the document link in the page: + +```html +{% for block in page.documents %} + <a href="{{ block.value.url }}">{{ block.value.title }}</a> +{% endfor %} +``` + + +## Working documents and collections + +Documents in Wagtail can be organized within [collections](https://docs.wagtail.org/en/v4.0/editor_manual/documents_images_snippets/collections.html). Collections provide a way to group related documents. You can cross-link documents between collections and make them accessible through different parts of your site. + +Here's an example: + +```python +from wagtail.documents import get_document_model + +class PageWithCollection(Page): + collection = models.ForeignKey( + "wagtailcore.Collection", + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name='+', + verbose_name='Document Collection', + ) + + content_panels = Page.content_panels + [ + FieldPanel("collection"), + ] + + def get_context(self, request): + context = super().get_context(request) + documents = get_document_model().objects.filter(collection=self.collection) + context['documents'] = documents + return context + +``` + +Here’s an example template to access the document collection and render it: + +```html +{% extends "base.html" %} +{% load wagtailcore_tags %} + +{% block content %} + {% if documents %} + <h3>Documents:</h3> + <ul> + {% for document in documents %} + <li> + <a href="{{ document.url }}" target="_blank">{{ document.title }}</a> + </li> + {% endfor %} + </ul> + {% endif %} +{% endblock %} +``` + +## Making documents private + +If you want to restrict access to certain documents, you can place them in [private collections](https://guide.wagtail.org/en-latest/how-to-guides/manage-collections/#privacy-settings). + +Private collections are not publicly accessible, and their contents are only available to users with the appropriate permissions. + +## API access + +Documents in Wagtail can be accessed through the API via the `wagtail.documents.api.v2.views.DocumentsAPIViewSet`. This allows you to programmatically interact with documents, retrieve their details, and perform various operations. + +For more details, you can refer to the [API section](api_v2_configure_endpoints) that provides additional information and usage examples. diff --git a/docs/advanced_topics/documents/storing_and_serving.md b/docs/advanced_topics/documents/storing_and_serving.md new file mode 100644 index 0000000000..4e469a9f9a --- /dev/null +++ b/docs/advanced_topics/documents/storing_and_serving.md @@ -0,0 +1,60 @@ +(storing_and_serving)= + +# Storing and serving + +Wagtail follows [Django’s conventions for managing uploaded files](django:topics/files). For configuration of `FileSystemStorage` and more information on handling user uploaded files, see [](user_uploaded_files). + +## File storage location + +Wagtail uses the [DEFAULT_FILE_STORAGE](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-DEFAULT_FILE_STORAGE) setting to determine where and how user-uploaded files are stored. By default, Wagtail stores files in the local filesystem. + +## Serving documents + +Document serving is controlled by the [WAGTAILDOCS_SERVE_METHOD](wagtaildocs_serve_method) method. It provides a number of serving methods which trade some of the strictness of the permission check that occurs when normally handling a document request for performance. + +The serving methods provided are `direct`, `redirect` and `serve_view`, with `redirect` method being the default when `WAGTAILDOCS_SERVE_METHOD` is unspecified or set to `None`. For example: + +```python +WAGTAILDOCS_SERVE_METHOD = "redirect" +``` + +## Content types + +Wagtail provides the [WAGTAILDOCS_CONTENT_TYPES](wagtaildocs_content_types) setting to specify which document content types are allowed to be uploaded. For example: + +```python +WAGTAILDOCS_CONTENT_TYPES = { + 'pdf': 'application/pdf', + 'txt': 'text/plain', +} +``` + +## Inline content types + +Inline content types can be specified using [WAGTAILDOCS_INLINE_CONTENT_TYPES](wagtaildocs_inline_content_types), are displayed within the rich text editor. + +For example: + +```python +WAGTAILDOCS_INLINE_CONTENT_TYPES = ['application/pdf', 'text/plain'] +``` + +## File extensions + +Wagtail allows you to specify the permitted file extensions for document uploads using the [WAGTAILDOCS_EXTENSIONS](wagtaildocs_extensions) setting. + +It also validates the extensions using Django's [FileExtensionValidator](django:ref/validators#fileextensionvalidator). For example: + +```python +WAGTAILDOCS_EXTENSIONS = ['pdf', 'docx'] +``` + +## Document password required template + +Wagtail provides the `DOCUMENT_PASSWORD_REQUIRED_TEMPLATE` setting to use a custom template when a password is required to access a protected document. Read more about [](private_pages). + +Here's an example: + +```python +DOCUMENT_PASSWORD_REQUIRED_TEMPLATE = 'myapp/document_password_required.html' +``` diff --git a/docs/advanced_topics/documents/title_generation_on_upload.md b/docs/advanced_topics/documents/title_generation_on_upload.md index 790e80fb4b..b64fb9d071 100644 --- a/docs/advanced_topics/documents/title_generation_on_upload.md +++ b/docs/advanced_topics/documents/title_generation_on_upload.md @@ -12,7 +12,7 @@ You can customise the resolved value of this title using a JavaScript [event lis The simplest way to add JavaScript to the editor is via the [`insert_global_admin_js` hook](insert_global_admin_js). However, any JavaScript that adds an event listener will work. -## DOM Event +## DOM event The event name to listen to is `'wagtail:documents-upload'`. It will be dispatched on the document upload `form`. The event's `detail` attribute will contain: @@ -30,7 +30,7 @@ The event will 'bubble' up so that you can simply add a global `document` listen See MDN for more information about [custom JavaScript events](https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events). -## Code Examples +## Code examples ### Adding the file extension to the start of the title diff --git a/docs/reference/settings.md b/docs/reference/settings.md index 458e014988..888d5ddf18 100644 --- a/docs/reference/settings.md +++ b/docs/reference/settings.md @@ -373,6 +373,8 @@ WAGTAILDOCS_DOCUMENT_MODEL = 'myapp.MyDocument' This setting lets you provide your own document model for use in Wagtail, which should extend the built-in `AbstractDocument` class. +(wagtaildocs_document_form_base)= + ### `WAGTAILDOCS_DOCUMENT_FORM_BASE` ```python diff --git a/docs/releases/6.0.md b/docs/releases/6.0.md index 943f61cae5..8ee1df1c97 100644 --- a/docs/releases/6.0.md +++ b/docs/releases/6.0.md @@ -35,6 +35,7 @@ depth: 1 ### Documentation * Document, for contributors, the use of translate string literals passed as arguments to tags and filters using `_()` within templates (Chiemezuo Akujobi) + * Document all features for the Documents app in one location, see [](../advanced_topics/documents/index) (Neeraj Yetheendran) ### Maintenance