Browse Source

documentation - migrate advanced_topics/images/** to md

Thiago Costa de Souza 2 years ago
parent
commit
4424d23fa4

+ 1 - 3
docs/advanced_topics/embeds.md

@@ -19,7 +19,7 @@ You can use any of the following methods to call the module:
 
 Wagtail's default rich text editor has a "media" icon that allows embeds to be
 placed into rich text. You don't have to do anything to enable this; just make
-sure the rich text field's content is being passed through the ``|richtext``
+sure the rich text field's content is being passed through the `|richtext`
 filter in the template as this is what calls the embeds module to fetch and
 nest the embed code.
 
@@ -182,7 +182,6 @@ perform the request.
 Wagtail will not try to run any other finder, even if the chosen one didn't
 return an embed.
 
-
 (facebook_and_instagram_embeds)=
 
 ### Facebook and Instagram
@@ -235,7 +234,6 @@ By passing `'omitscript': True` in the configuration, you can indicate that thes
 tags should be omitted from the embed HTML. Note that you will then have to take care of
 loading this script yourself.
 
-
 (Embedly)=
 
 ### Embed.ly

+ 2 - 3
docs/advanced_topics/images/animated_gifs.rst → docs/advanced_topics/images/animated_gifs.md

@@ -1,11 +1,10 @@
-Animated GIF support
-====================
+# Animated GIF support
 
 Pillow, Wagtail's default image library, doesn't support animated
 GIFs.
 
 To get animated GIF support, you will have to
-`install Wand <https://docs.wand-py.org/en/0.6.7/guide/install.html>`_.
+[install Wand](https://docs.wand-py.org/en/0.6.7/guide/install.html).
 Wand is a binding to ImageMagick so make sure that has been installed as well.
 
 When installed, Wagtail will automatically use Wand for resizing GIF

+ 56 - 0
docs/advanced_topics/images/changing_rich_text_representation.md

@@ -0,0 +1,56 @@
+(changing_rich_text_representation)=
+
+# Changing rich text representation
+
+The HTML representation of an image in rich text can be customised - for example, to display captions or custom fields.
+
+To do this requires subclassing `Format` (see [](rich_text_image_formats)), and overriding its `image_to_html` method.
+
+You may then register formats of your subclass using `register_image_format` as usual.
+
+```python
+# image_formats.py
+from wagtail.images.formats import Format, register_image_format
+
+
+class SubclassedImageFormat(Format):
+
+    def image_to_html(self, image, alt_text, extra_attributes=None):
+
+        custom_html = # the custom HTML representation of your image here
+                        # in Format, the image's rendition.img_tag(extra_attributes) is used to generate the HTML
+                        # representation
+
+        return custom_html
+
+
+register_image_format(
+    SubclassedImageFormat('subclassed_format', 'Subclassed Format', classnames, filter_spec)
+)
+```
+
+As an example, let's say you want the alt text to be displayed as a caption for the image as well:
+
+```python
+# image_formats.py
+from django.utils.html import format_html
+from wagtail.images.formats import Format, register_image_format
+
+
+class CaptionedImageFormat(Format):
+
+    def image_to_html(self, image, alt_text, extra_attributes=None):
+
+        default_html = super().image_to_html(image, alt_text, extra_attributes)
+
+        return format_html("{}<figcaption>{}</figcaption>", default_html, alt_text)
+
+
+register_image_format(
+    CaptionedImageFormat('captioned_fullwidth', 'Full width captioned', 'bodytext-image', 'width-750')
+)
+```
+
+```{note}
+Any custom HTML image features will not be displayed in the Draftail editor, only on the published page.
+```

+ 0 - 57
docs/advanced_topics/images/changing_rich_text_representation.rst

@@ -1,57 +0,0 @@
-.. _changing_rich_text_representation:
-
-=================================
-Changing rich text representation
-=================================
-
-The HTML representation of an image in rich text can be customised - for example, to display captions or custom fields.
-
-To do this requires subclassing ``Format`` (see :ref:`rich_text_image_formats`), and overriding its ``image_to_html`` method.
-
-You may then register formats of your subclass using ``register_image_format`` as usual.
-
-.. code-block:: python
-
-    # image_formats.py
-    from wagtail.images.formats import Format, register_image_format
-
-
-    class SubclassedImageFormat(Format):
-
-        def image_to_html(self, image, alt_text, extra_attributes=None):
-
-            custom_html = # the custom HTML representation of your image here
-                          # in Format, the image's rendition.img_tag(extra_attributes) is used to generate the HTML
-                          # representation
-
-            return custom_html
-
-
-    register_image_format(
-        SubclassedImageFormat('subclassed_format', 'Subclassed Format', classnames, filter_spec)
-    )
-
-As an example, let's say you want the alt text to be displayed as a caption for the image as well:
-
-.. code-block:: python
-
-    # image_formats.py
-    from django.utils.html import format_html
-    from wagtail.images.formats import Format, register_image_format
-
-
-    class CaptionedImageFormat(Format):
-
-        def image_to_html(self, image, alt_text, extra_attributes=None):
-
-            default_html = super().image_to_html(image, alt_text, extra_attributes)
-
-            return format_html("{}<figcaption>{}</figcaption>", default_html, alt_text)
-
-
-    register_image_format(
-        CaptionedImageFormat('captioned_fullwidth', 'Full width captioned', 'bodytext-image', 'width-750')
-    )
-
-.. note::
-    Any custom HTML image features will not be displayed in the Draftail editor, only on the published page.

+ 3 - 3
docs/advanced_topics/images/custom_image_model.md

@@ -7,8 +7,8 @@ to images.
 
 To do this, you need to add two models to your project:
 
-- The image model itself that inherits from `wagtail.images.models.AbstractImage`. This is where you would add your additional fields
-- The renditions model that inherits from `wagtail.images.models.AbstractRendition`. This is used to store renditions for the new model.
+-   The image model itself that inherits from `wagtail.images.models.AbstractImage`. This is where you would add your additional fields
+-   The renditions model that inherits from `wagtail.images.models.AbstractRendition`. This is used to store renditions for the new model.
 
 Here's an example:
 
@@ -66,4 +66,4 @@ work as before but would need to be updated in order to see any new images.
 .. autofunction:: get_image_model
 
 .. autofunction:: get_image_model_string
-```
+```

+ 125 - 0
docs/advanced_topics/images/feature_detection.md

@@ -0,0 +1,125 @@
+(image_feature_detection)=
+
+# Feature Detection
+
+Wagtail has the ability to automatically detect faces and features inside your images and crop the images to those features.
+
+Feature detection uses third-party tools to detect faces/features in an image when the image is uploaded. The detected features are stored internally as a focal point in the `focal_point_{x, y, width, height}` fields on the `Image` model. These fields are used by the `fill` image filter when an image is rendered in a template to crop the image.
+
+## Installation
+
+Two third-party tools are known to work with Wagtail: One based on [OpenCV](https://opencv.org/) for general feature detection and one based on [Rustface](https://github.com/torchbox/rustface-py/) for face detection.
+
+### OpenCV on Debian/Ubuntu
+
+Feature detection requires [OpenCV](https://opencv.org/) which can be a bit tricky to install as it's not currently pip-installable.
+
+There is more than one way to install these components, but in each case you will need to test that both OpenCV itself _and_ the Python interface have been correctly installed.
+
+#### Install `opencv-python`
+
+[opencv-python](https://pypi.org/project/opencv-python/) is available on PyPI.
+It includes a Python interface to OpenCV, as well as the statically-built OpenCV binaries themselves.
+
+To install:
+
+```console
+$ pip install opencv-python
+```
+
+Depending on what else is installed on your system, this may be all that is required. On lighter-weight Linux systems, you may need to identify and install missing system libraries (for example, a slim version of Debian Stretch requires `libsm6 libxrender1 libxext6` to be installed with `apt`).
+
+#### Install a system-level package
+
+A system-level package can take care of all of the required components. Check what is available for your operating system. For example, [python-opencv](https://packages.debian.org/stretch/python-opencv) is available for Debian; it installs OpenCV itself, and sets up Python bindings.
+
+However, it may make incorrect assumptions about how you're using Python (for example, which version you're using) - test as described below.
+
+#### Testing the installation
+
+Test the installation:
+
+```python
+python3
+>>> import cv2
+```
+
+An error such as:
+
+```python
+ImportError: libSM.so.6: cannot open shared object file: No such file or directory
+```
+
+indicates that a required system library (in this case `libsm6`) has not been installed.
+
+On the other hand,
+
+```python
+ModuleNotFoundError: No module named 'cv2'
+```
+
+means that the Python components have not been set up correctly in your Python environment.
+
+If you don't get an import error, installation has probably been successful.
+
+### Rustface
+
+[Rustface](https://github.com/torchbox/rustface-py/) is Python library with prebuilt wheel files provided for Linux and macOS. Although implemented in Rust it is pip-installable:
+
+```console
+$ pip install wheel
+$ pip install rustface
+```
+
+#### Registering with Willow
+
+Rustface provides a plug-in that needs to be registered with [Willow](https://github.com/wagtail/Willow).
+
+This should be done somewhere that gets run on application startup:
+
+```python
+from willow.registry import registry
+import rustface.willow
+
+registry.register_plugin(rustface.willow)
+```
+
+For example, in an app's [AppConfig.ready](https://docs.djangoproject.com/en/2.2/ref/applications/#django.apps.AppConfig.ready).
+
+## Cropping
+
+The face detection algorithm produces a focal area that is tightly cropped to the face rather than the whole head.
+
+For images with a single face this can be okay in some cases, e.g. thumbnails, it might be overly tight for "headshots".
+Image renditions can encompass more of the head by reducing the crop percentage (`-c<percentage>`), at the end of the resize-rule, down to as low as 0%:
+
+```html+django
+{% image page.photo fill-200x200-c0 %}
+```
+
+## Switching on feature detection in Wagtail
+
+Once installed, you need to set the `WAGTAILIMAGES_FEATURE_DETECTION_ENABLED` setting to `True` to automatically detect faces/features whenever a new image is uploaded in to Wagtail or when an image without a focal point is saved (this is done via a pre-save signal handler):
+
+```python
+# settings.py
+
+WAGTAILIMAGES_FEATURE_DETECTION_ENABLED = True
+```
+
+## Manually running feature detection
+
+If you already have images in your Wagtail site and would like to run feature detection on them, or you want to apply feature detection selectively when the `WAGTAILIMAGES_FEATURE_DETECTION_ENABLED` is set to `False` you can run it manually using the `get_suggested_focal_point()` method on the `Image` model.
+
+For example, you can manually run feature detection on all images by running the following code in the python shell:
+
+```python
+from wagtail.images import get_image_model
+
+Image = get_image_model()
+
+for image in Image.objects.all():
+    if not image.has_focal_point():
+        image.set_focal_point(image.get_suggested_focal_point())
+        image.save()
+```

+ 0 - 151
docs/advanced_topics/images/feature_detection.rst

@@ -1,151 +0,0 @@
-.. _image_feature_detection:
-
-Feature Detection
-=================
-
-Wagtail has the ability to automatically detect faces and features inside your images and crop the images to those features.
-
-Feature detection uses third-party tools to detect faces/features in an image when the image is uploaded. The detected features are stored internally as a focal point in the ``focal_point_{x, y, width, height}`` fields on the ``Image`` model. These fields are used by the ``fill`` image filter when an image is rendered in a template to crop the image.
-
-
-Installation
-------------
-
-Two third-party tools are known to work with Wagtail: One based on OpenCV_ for general feature detection and one based on Rustface_ for face detection.
-
-.. _OpenCV: https://opencv.org/
-
-.. _Rustface: https://github.com/torchbox/rustface-py/
-
-OpenCV on Debian/Ubuntu
-^^^^^^^^^^^^^^^^^^^^^^^
-
-Feature detection requires OpenCV_ which can be a bit tricky to install as it's not currently pip-installable.
-
-There is more than one way to install these components, but in each case you will need to test that both OpenCV itself *and* the Python interface have been correctly installed.
-
-
-Install ``opencv-python``
-`````````````````````````
-
-`opencv-python <https://pypi.org/project/opencv-python/>`_ is available on PyPI.
-It includes a Python interface to OpenCV, as well as the statically-built OpenCV binaries themselves.
-
-To install:
-
-.. code-block:: console
-
-    $ pip install opencv-python
-
-Depending on what else is installed on your system, this may be all that is required. On lighter-weight Linux systems, you may need to identify and install missing system libraries (for example, a slim version of Debian Stretch requires ``libsm6 libxrender1 libxext6`` to be installed with ``apt``).
-
-
-Install a system-level package
-``````````````````````````````
-
-A system-level package can take care of all of the required components. Check what is available for your operating system. For example, `python-opencv <https://packages.debian.org/stretch/python-opencv>`_ is available for Debian; it installs OpenCV itself, and sets up Python bindings.
-
-However, it may make incorrect assumptions about how you're using Python (for example, which version you're using) - test as described below.
-
-
-Testing the installation
-````````````````````````
-
-Test the installation::
-
-    python3
-    >>> import cv2
-
-An error such as::
-
-    ImportError: libSM.so.6: cannot open shared object file: No such file or directory
-
-indicates that a required system library (in this case ``libsm6``) has not been installed.
-
-On the other hand,
-
-::
-
-    ModuleNotFoundError: No module named 'cv2'
-
-means that the Python components have not been set up correctly in your Python environment.
-
-If you don't get an import error, installation has probably been successful.
-
-
-Rustface
-^^^^^^^^
-
-Rustface_ is Python library with prebuilt wheel files provided for Linux and macOS. Although implemented in Rust it is pip-installable:
-
-.. code-block:: console
-
-    $ pip install wheel
-    $ pip install rustface
-
-
-Registering with Willow
-```````````````````````
-
-Rustface provides a plug-in that needs to be registered with Willow_.
-
-This should be done somewhere that gets run on application startup:
-
-.. code-block:: python
-
-    from willow.registry import registry
-    import rustface.willow
-
-    registry.register_plugin(rustface.willow)
-
-For example, in an app's AppConfig.ready_.
-
-.. _Willow: https://github.com/wagtail/Willow
-
-.. _AppConfig.ready: https://docs.djangoproject.com/en/2.2/ref/applications/#django.apps.AppConfig.ready
-
-
-Cropping
---------
-
-The face detection algorithm produces a focal area that is tightly cropped to the face rather than the whole head.
-
-For images with a single face this can be okay in some cases, e.g. thumbnails, it might be overly tight for "headshots".
-Image renditions can encompass more of the head by reducing the crop percentage (``-c<percentage>``), at the end of the resize-rule, down to as low as 0%:
-
-.. code-block:: html+django
-
-    {% image page.photo fill-200x200-c0 %}
-
-
-Switching on feature detection in Wagtail
------------------------------------------
-
-Once installed, you need to set the ``WAGTAILIMAGES_FEATURE_DETECTION_ENABLED`` setting to ``True`` to automatically detect faces/features whenever a new image is uploaded in to Wagtail or when an image without a focal point is saved (this is done via a pre-save signal handler):
-
-.. code-block:: python
-
-    # settings.py
-
-    WAGTAILIMAGES_FEATURE_DETECTION_ENABLED = True
-
-
-Manually running feature detection
-----------------------------------
-
-If you already have images in your Wagtail site and would like to run feature detection on them, or you want to apply feature detection selectively when the ``WAGTAILIMAGES_FEATURE_DETECTION_ENABLED`` is set to ``False`` you can run it manually using the `get_suggested_focal_point()` method on the ``Image`` model.
-
-For example, you can manually run feature detection on all images by running the following code in the python shell:
-
-.. code-block:: python
-
-    from wagtail.images import get_image_model
-
-    Image = get_image_model()
-
-    for image in Image.objects.all():
-        if not image.has_focal_point():
-            image.set_focal_point(image.get_suggested_focal_point())
-            image.save()
-
-

+ 41 - 0
docs/advanced_topics/images/focal_points.md

@@ -0,0 +1,41 @@
+# Focal points
+
+Focal points are used to indicate to Wagtail the area of an image that contains the subject.
+This is used by the `fill` filter to focus the cropping on the subject, and avoid cropping into it.
+
+Focal points can be defined manually by a Wagtail user, or automatically by using face or feature detection.
+
+(rendition_background_position_style)=
+
+## Setting the `background-position` inline style based on the focal point
+
+When using a Wagtail image as the background of an element, you can use the `.background_position_style`
+attribute on the rendition to position the rendition based on the focal point in the image:
+
+```html+django
+{% image page.image width-1024 as image %}
+
+<div style="background-image: url('{{ image.url }}'); {{ image.background_position_style }}">
+</div>
+```
+
+## Accessing the focal point in templates
+
+You can access the focal point in the template by accessing the `.focal_point` attribute of a rendition:
+
+```html+django
+{% load wagtailimages %}
+
+{% image myimage width-800 as myrendition %}
+
+<img
+    src="{{ myrendition.url }}"
+    alt="{{ myimage.title }}"
+    {% if myrendition.focal_point %}
+        data-focus-x="{{ myrendition.focal_point.centroid.x }}"
+        data-focus-y="{{ myrendition.focal_point.centroid.y }}"
+        data-focus-width="{{ myrendition.focal_point.width }}"
+        data-focus-height="{{ myrendition.focal_point.height }}"
+    {% endif %}
+/>
+```

+ 0 - 44
docs/advanced_topics/images/focal_points.rst

@@ -1,44 +0,0 @@
-Focal points
-============
-
-Focal points are used to indicate to Wagtail the area of an image that contains the subject.
-This is used by the ``fill`` filter to focus the cropping on the subject, and avoid cropping into it.
-
-Focal points can be defined manually by a Wagtail user, or automatically by using face or feature detection.
-
-.. _rendition_background_position_style:
-
-Setting the ``background-position`` inline style based on the focal point
--------------------------------------------------------------------------
-
-When using a Wagtail image as the background of an element, you can use the ``.background_position_style``
-attribute on the rendition to position the rendition based on the focal point in the image:
-
-.. code-block:: html+Django
-
-    {% image page.image width-1024 as image %}
-
-    <div style="background-image: url('{{ image.url }}'); {{ image.background_position_style }}">
-    </div>
-
-Accessing the focal point in templates
---------------------------------------
-
-You can access the focal point in the template by accessing the ``.focal_point`` attribute of a rendition:
-
-.. code-block:: html+Django
-
-    {% load wagtailimages %}
-
-    {% image myimage width-800 as myrendition %}
-
-    <img
-        src="{{ myrendition.url }}"
-        alt="{{ myimage.title }}"
-        {% if myrendition.focal_point %}
-            data-focus-x="{{ myrendition.focal_point.centroid.x }}"
-            data-focus-y="{{ myrendition.focal_point.centroid.y }}"
-            data-focus-width="{{ myrendition.focal_point.width }}"
-            data-focus-height="{{ myrendition.focal_point.height }}"
-        {% endif %}
-    />

+ 44 - 0
docs/advanced_topics/images/image_file_formats.md

@@ -0,0 +1,44 @@
+(image_file_formats)=
+
+# Image file formats
+
+## Using the picture element
+
+The [picture element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
+can be used with the `format-<type>` image operation to specify different
+image formats and let the browser choose the one it prefers. For example:
+
+```python
+{% load wagtailimages_tags %}
+
+<picture>
+    {% image myimage width-1000 format-webp as image_webp %}
+    <source srcset="{{ image_webp.url }}" type="image/webp">
+
+    {% image myimage width-1000 format-png as image_png %}
+    <source srcset="{{ image_png.url }}" type="image/png">
+
+    {% image myimage width-1000 format-png %}
+</picture>
+```
+
+### Customising output formats
+
+By default all `bmp` and `webp` images are converted to the `png` format
+when no image output format is given.
+
+The default conversion mapping can be changed by setting the
+`WAGTAILIMAGES_FORMAT_CONVERSIONS` to a dictionary which maps the input type
+to an output type.
+
+For example:
+
+```python
+    WAGTAILIMAGES_FORMAT_CONVERSIONS = {
+        'bmp': 'jpeg',
+        'webp': 'webp',
+    }
+```
+
+will convert `bmp` images to `jpeg` and disable the default `webp`
+to `png` conversion.

+ 0 - 47
docs/advanced_topics/images/image_file_formats.rst

@@ -1,47 +0,0 @@
-.. _image_file_formats:
-
-Image file formats
-==================
-
-Using the picture element
--------------------------
-
-The `picture element <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture>`_
-can be used with the ``format-<type>`` image operation to specify different
-image formats and let the browser choose the one it prefers. For example:
-
-.. code-block:: python
-
-    {% load wagtailimages_tags %}
-
-    <picture>
-        {% image myimage width-1000 format-webp as image_webp %}
-        <source srcset="{{ image_webp.url }}" type="image/webp">
-
-        {% image myimage width-1000 format-png as image_png %}
-        <source srcset="{{ image_png.url }}" type="image/png">
-
-        {% image myimage width-1000 format-png %}
-    </picture>
-
-Customising output formats
---------------------------
-
-By default all ``bmp`` and ``webp`` images are converted to the ``png`` format
-when no image output format is given.
-
-The default conversion mapping can be changed by setting the
-``WAGTAILIMAGES_FORMAT_CONVERSIONS`` to a dictionary which maps the input type
-to an output type.
-
-For example:
-
-.. code-block:: python
-
-    WAGTAILIMAGES_FORMAT_CONVERSIONS = {
-        'bmp': 'jpeg',
-        'webp': 'webp',
-    }
-
-will convert ``bmp`` images to ``jpeg`` and disable the default ``webp``
-to ``png`` conversion.

+ 163 - 0
docs/advanced_topics/images/image_serve_view.md

@@ -0,0 +1,163 @@
+(using_images_outside_wagtail)=
+
+# Dynamic image serve view
+
+In most cases, developers wanting to generate image renditions in Python should use the `get_rendition()`
+method. See [](image_renditions).
+
+If you need to be able to generate image versions for an _external_ system such as a blog or mobile app,
+Wagtail provides a view for dynamically generating renditions of images by calling a unique URL.
+
+The view takes an image id, filter spec and security signature in the URL. If
+these parameters are valid, it serves an image file matching that criteria.
+
+Like the `{% image %}` tag, the rendition is generated on the first call and
+subsequent calls are served from a cache.
+
+## Setup
+
+Add an entry for the view into your URLs configuration:
+
+```python
+from wagtail.images.views.serve import ServeView
+
+urlpatterns = [
+    ...
+
+    re_path(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', ServeView.as_view(), name='wagtailimages_serve'),
+
+    ...
+
+    # Ensure that the wagtailimages_serve line appears above the default Wagtail page serving route
+    re_path(r'', include(wagtail_urls)),
+]
+```
+
+## Usage
+
+### Image URL generator UI
+
+When the dynamic serve view is enabled, an image URL generator in the admin
+interface becomes available automatically. This can be accessed through the edit
+page of any image by clicking the "URL generator" button on the right hand side.
+
+This interface allows editors to generate URLs to cropped versions of the image.
+
+### Generating dynamic image URLs in Python
+
+Dynamic image URLs can also be generated using Python code and served to a
+client over an API or used directly in the template.
+
+One advantage of using dynamic image URLs in the template is that they do not
+block the initial response while rendering like the `{% image %}` tag does.
+
+The `generate_image_url` function in `wagtail.images.views.serve` is a convenience
+method to generate a dynamic image URL.
+
+Here's an example of this being used in a view:
+
+```python
+def display_image(request, image_id):
+    image = get_object_or_404(Image, id=image_id)
+
+    return render(request, 'display_image.html', {
+        'image_url': generate_image_url(image, 'fill-100x100')
+    })
+```
+
+Image operations can be chained by joining them with a `|` character:
+
+```python
+return render(request, 'display_image.html', {
+    'image_url': generate_image_url(image, 'fill-100x100|jpegquality-40')
+})
+```
+
+In your templates:
+
+```html+django
+{% load wagtailimages_tags %}
+...
+
+<!-- Get the url for the image scaled to a width of 400 pixels: -->
+{% image_url page.photo "width-400" %}
+
+<!-- Again, but this time as a square thumbnail: -->
+{% image_url page.photo "fill-100x100|jpegquality-40" %}
+
+<!-- This time using our custom image serve view: -->
+{% image_url page.photo "width-400" "mycustomview_serve" %}
+```
+
+You can pass an optional view name that will be used to serve the image through. The default is `wagtailimages_serve`
+
+## Advanced configuration
+
+(image_serve_view_redirect_action)=
+
+### Making the view redirect instead of serve
+
+By default, the view will serve the image file directly. This behaviour can be
+changed to a 301 redirect instead which may be useful if you host your images
+externally.
+
+To enable this, pass `action='redirect'` into the `ServeView.as_view()`
+method in your urls configuration:
+
+```python
+from wagtail.images.views.serve import ServeView
+
+urlpatterns = [
+    ...
+
+    re_path(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', ServeView.as_view(action='redirect'), name='wagtailimages_serve'),
+]
+```
+
+(image_serve_view_sendfile)=
+
+## Integration with django-sendfile
+
+[django-sendfile](https://github.com/johnsensible/django-sendfile) offloads the job of transferring the image data to the web
+server instead of serving it directly from the Django application. This could
+greatly reduce server load in situations where your site has many images being
+downloaded but you're unable to use a [](caching_proxy) or a CDN.
+
+You firstly need to install and configure django-sendfile and configure your
+web server to use it. If you haven't done this already, please refer to the
+[installation docs](https://github.com/johnsensible/django-sendfile#django-sendfile).
+
+To serve images with django-sendfile, you can use the `SendFileView` class.
+This view can be used out of the box:
+
+```python
+from wagtail.images.views.serve import SendFileView
+
+urlpatterns = [
+    ...
+
+    re_path(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', SendFileView.as_view(), name='wagtailimages_serve'),
+]
+```
+
+You can customise it to override the backend defined in the `SENDFILE_BACKEND`
+setting:
+
+```python
+from wagtail.images.views.serve import SendFileView
+from project.sendfile_backends import MyCustomBackend
+
+class MySendFileView(SendFileView):
+    backend = MyCustomBackend
+```
+
+You can also customise it to serve private files. For example, if the only need
+is to be authenticated (e.g. for Django >= 1.9):
+
+```python
+from django.contrib.auth.mixins import LoginRequiredMixin
+from wagtail.images.views.serve import SendFileView
+
+class PrivateSendFileView(LoginRequiredMixin, SendFileView):
+    raise_exception = True
+```

+ 0 - 176
docs/advanced_topics/images/image_serve_view.rst

@@ -1,176 +0,0 @@
-.. _using_images_outside_wagtail:
-
-========================
-Dynamic image serve view
-========================
-
-In most cases, developers wanting to generate image renditions in Python should use the ``get_rendition()``
-method. See :ref:`image_renditions`.
-
-If you need to be able to generate image versions for an *external* system such as a blog or mobile app,
-Wagtail provides a view for dynamically generating renditions of images by calling a unique URL.
-
-The view takes an image id, filter spec and security signature in the URL. If
-these parameters are valid, it serves an image file matching that criteria.
-
-Like the ``{% image %}`` tag, the rendition is generated on the first call and
-subsequent calls are served from a cache.
-
-Setup
-=====
-
-Add an entry for the view into your URLs configuration:
-
-.. code-block:: python
-
-    from wagtail.images.views.serve import ServeView
-
-    urlpatterns = [
-        ...
-
-        re_path(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', ServeView.as_view(), name='wagtailimages_serve'),
-
-        ...
-
-        # Ensure that the wagtailimages_serve line appears above the default Wagtail page serving route
-        re_path(r'', include(wagtail_urls)),
-    ]
-
-Usage
-=====
-
-Image URL generator UI
-----------------------
-
-When the dynamic serve view is enabled, an image URL generator in the admin
-interface becomes available automatically. This can be accessed through the edit
-page of any image by clicking the "URL generator" button on the right hand side.
-
-This interface allows editors to generate URLs to cropped versions of the image.
-
-Generating dynamic image URLs in Python
----------------------------------------
-
-Dynamic image URLs can also be generated using Python code and served to a
-client over an API or used directly in the template.
-
-One advantage of using dynamic image URLs in the template is that they do not
-block the initial response while rendering like the ``{% image %}`` tag does.
-
-The ``generate_image_url`` function in ``wagtail.images.views.serve`` is a convenience
-method to generate a dynamic image URL.
-
-Here's an example of this being used in a view:
-
-.. code-block:: python
-
-    def display_image(request, image_id):
-        image = get_object_or_404(Image, id=image_id)
-
-        return render(request, 'display_image.html', {
-            'image_url': generate_image_url(image, 'fill-100x100')
-        })
-
-
-Image operations can be chained by joining them with a ``|`` character:
-
-.. code-block:: python
-
-        return render(request, 'display_image.html', {
-            'image_url': generate_image_url(image, 'fill-100x100|jpegquality-40')
-        })
-
-
-In your templates:
-
-.. code-block:: html+django
-
-    {% load wagtailimages_tags %}
-    ...
-
-    <!-- Get the url for the image scaled to a width of 400 pixels: -->
-    {% image_url page.photo "width-400" %}
-
-    <!-- Again, but this time as a square thumbnail: -->
-    {% image_url page.photo "fill-100x100|jpegquality-40" %}
-
-    <!-- This time using our custom image serve view: -->
-    {% image_url page.photo "width-400" "mycustomview_serve" %}
-
-You can pass an optional view name that will be used to serve the image through. The default is ``wagtailimages_serve``
-
-Advanced configuration
-======================
-
-.. _image_serve_view_redirect_action:
-
-Making the view redirect instead of serve
------------------------------------------
-
-By default, the view will serve the image file directly. This behaviour can be
-changed to a 301 redirect instead which may be useful if you host your images
-externally.
-
-To enable this, pass ``action='redirect'`` into the ``ServeView.as_view()``
-method in your urls configuration:
-
-.. code-block:: python
-
-   from wagtail.images.views.serve import ServeView
-
-   urlpatterns = [
-       ...
-
-       re_path(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', ServeView.as_view(action='redirect'), name='wagtailimages_serve'),
-   ]
-
-.. _image_serve_view_sendfile:
-
-Integration with django-sendfile
---------------------------------
-
-`django-sendfile`_ offloads the job of transferring the image data to the web
-server instead of serving it directly from the Django application. This could
-greatly reduce server load in situations where your site has many images being
-downloaded but you're unable to use a :ref:`caching_proxy` or a CDN.
-
-.. _django-sendfile: https://github.com/johnsensible/django-sendfile
-
-You firstly need to install and configure django-sendfile and configure your
-web server to use it. If you haven't done this already, please refer to the
-`installation docs <https://github.com/johnsensible/django-sendfile#django-sendfile>`_.
-
-To serve images with django-sendfile, you can use the ``SendFileView`` class.
-This view can be used out of the box:
-
-.. code-block:: python
-
-   from wagtail.images.views.serve import SendFileView
-
-   urlpatterns = [
-       ...
-
-       re_path(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', SendFileView.as_view(), name='wagtailimages_serve'),
-   ]
-
-You can customise it to override the backend defined in the ``SENDFILE_BACKEND``
-setting:
-
-.. code-block:: python
-
-    from wagtail.images.views.serve import SendFileView
-    from project.sendfile_backends import MyCustomBackend
-
-    class MySendFileView(SendFileView):
-        backend = MyCustomBackend
-
-You can also customise it to serve private files. For example, if the only need
-is to be authenticated (e.g. for Django >= 1.9):
-
-.. code-block:: python
-
-    from django.contrib.auth.mixins import LoginRequiredMixin
-    from wagtail.images.views.serve import SendFileView
-
-    class PrivateSendFileView(LoginRequiredMixin, SendFileView):
-        raise_exception = True

+ 16 - 0
docs/advanced_topics/images/index.md

@@ -0,0 +1,16 @@
+# Images
+
+```{toctree}
+---
+maxdepth: 2
+---
+renditions
+animated_gifs
+image_file_formats
+custom_image_model
+changing_rich_text_representation
+feature_detection
+image_serve_view
+focal_points
+title_generation_on_upload
+```

+ 0 - 16
docs/advanced_topics/images/index.rst

@@ -1,16 +0,0 @@
-Images
-======
-
-
-.. toctree::
-    :maxdepth: 2
-
-    renditions
-    animated_gifs
-    image_file_formats
-    custom_image_model
-    changing_rich_text_representation
-    feature_detection
-    image_serve_view
-    focal_points
-    title_generation_on_upload

+ 103 - 0
docs/advanced_topics/images/renditions.md

@@ -0,0 +1,103 @@
+(image_renditions)=
+
+# Generating renditions in Python
+
+Rendered versions of original images generated by the Wagtail `{% image %}` template tag are called "renditions",
+and are stored as new image files in the site's `[media]/images` directory on the first invocation.
+
+Image renditions can also be generated dynamically from Python via the native `get_rendition()` method, for example:
+
+```python
+newimage = myimage.get_rendition('fill-300x150|jpegquality-60')
+```
+
+If `myimage` had a filename of `foo.jpg`, a new rendition of the image file called
+`foo.fill-300x150.jpegquality-60.jpg` would be generated and saved into the site's `[media]/images` directory.
+Argument options are identical to the `{% image %}` template tag's filter spec, and should be separated with `|`.
+
+The generated `Rendition` object will have properties specific to that version of the image, such as
+`url`, `width` and `height`, so something like this could be used in an API generator, for example:
+
+```python
+url = myimage.get_rendition('fill-300x186|jpegquality-60').url
+```
+
+Properties belonging to the original image from which the generated Rendition was created, such as `title`, can
+be accessed through the Rendition's `image` property:
+
+```python
+    >>> newimage.image.title
+    'Blue Sky'
+    >>> newimage.image.is_landscape()
+    True
+```
+
+See also: [](image_tag)
+
+(prefetching_image_renditions)=
+
+## Prefetching image renditions
+
+```{versionadded} 3.0
+This following guidance is only applicable in Wagtail versions 3.0 and above.
+```
+
+When using a queryset to render a list of objects with images, you can make use of Django's built-in `prefetch_related()` queryset method to prefetch the renditions needed for rendering with a single additional query. For long lists of items, or where multiple renditions are used for each item, this can provide a significant boost to performance.
+
+For example, say you were rendering a list of events (with thumbnail images for each). Your code might look something like this:
+
+```python
+def get_events():
+    return EventPage.objects.live().select_related("listing_image")
+```
+
+The above can be modified slightly to prefetch the renditions for listing images:
+
+```python
+def get_events():
+    return EventPage.objects.live().select_related("listing_image").prefetch_related("listing_image__renditions")
+```
+
+If images in your project tend to have very large numbers of renditions, and you know in advance the ones you need, you might want to consider using a `Prefetch` object to select only the renditions you need for rendering. For example:
+
+```python
+from django.db.models import Prefetch
+from wagtail.images import get_image_model
+
+
+def get_events():
+    # These are the renditions required for rendering
+    renditions_queryset = get_image_model().get_rendition_model().objects.filter(
+        filter_spec__in=["fill-300x186", "fill-600x400", "fill-940x680"]
+    )
+
+    # `Prefetch` is used to fetch only the required renditions
+    return EventPage.objects.live().select_related("listing_image").prefetch_related(
+        Prefetch("listing_image__renditions", queryset=renditions_queryset)
+    )
+```
+
+(image_rendition_methods)=
+
+## Model methods involved in rendition generation
+
+```{versionadded} 3.0
+The following method references are only applicable to Wagtail versions 3.0 and above.
+```
+
+The following `AbstractImage` model methods are involved in finding and generating a renditions. If using a custom image model, you can customise the behaviour of either of these methods by overriding them on your model:
+
+```{eval-rst}
+.. automodule:: wagtail.images.models
+
+.. class:: AbstractImage
+    :noindex:
+
+    .. automethod:: get_rendition
+
+    .. automethod:: find_existing_rendition
+
+    .. automethod:: create_rendition
+
+    .. automethod:: generate_rendition_file
+```

+ 0 - 102
docs/advanced_topics/images/renditions.rst

@@ -1,102 +0,0 @@
-.. _image_renditions:
-
-Generating renditions in Python
-=====================================
-
-Rendered versions of original images generated by the Wagtail ``{% image %}`` template tag are called "renditions",
-and are stored as new image files in the site's ``[media]/images`` directory on the first invocation.
-
-Image renditions can also be generated dynamically from Python via the native ``get_rendition()`` method, for example:
-
-.. code-block:: python
-
-    newimage = myimage.get_rendition('fill-300x150|jpegquality-60')
-
-If ``myimage`` had a filename of ``foo.jpg``, a new rendition of the image file called
-``foo.fill-300x150.jpegquality-60.jpg`` would be generated and saved into the site's ``[media]/images`` directory.
-Argument options are identical to the ``{% image %}`` template tag's filter spec, and should be separated with ``|``.
-
-The generated ``Rendition`` object will have properties specific to that version of the image, such as
-``url``, ``width`` and ``height``, so something like this could be used in an API generator, for example:
-
-.. code-block:: python
-
-    url = myimage.get_rendition('fill-300x186|jpegquality-60').url
-
-Properties belonging to the original image from which the generated Rendition was created, such as ``title``, can
-be accessed through the Rendition's ``image`` property:
-
-.. code-block:: python
-
-    >>> newimage.image.title
-    'Blue Sky'
-    >>> newimage.image.is_landscape()
-    True
-
-See also: :ref:`image_tag`
-
-.. _prefetching_image_renditions:
-
-Prefetching image renditions
-----------------------------
-
-.. versionadded:: 3.0
-    This following guidance is only applicable in Wagtail versions 3.0 and above.
-
-When using a queryset to render a list of objects with images, you can make use of Django's built-in ``prefetch_related()`` queryset method to prefetch the renditions needed for rendering with a single additional query. For long lists of items, or where multiple renditions are used for each item, this can provide a significant boost to performance.
-
-For example, say you were rendering a list of events (with thumbnail images for each). Your code might look something like this:
-
-.. code-block:: python
-
-    def get_events():
-        return EventPage.objects.live().select_related("listing_image")
-
-The above can be modified slightly to prefetch the renditions for listing images:
-
-.. code-block:: python
-
-    def get_events():
-        return EventPage.objects.live().select_related("listing_image").prefetch_related("listing_image__renditions")
-
-If images in your project tend to have very large numbers of renditions, and you know in advance the ones you need, you might want to consider using a ``Prefetch`` object to select only the renditions you need for rendering. For example:
-
-.. code-block:: python
-
-    from django.db.models import Prefetch
-    from wagtail.images import get_image_model
-
-
-    def get_events():
-        # These are the renditions required for rendering
-        renditions_queryset = get_image_model().get_rendition_model().objects.filter(
-            filter_spec__in=["fill-300x186", "fill-600x400", "fill-940x680"]
-        )
-
-        # `Prefetch` is used to fetch only the required renditions
-        return EventPage.objects.live().select_related("listing_image").prefetch_related(
-            Prefetch("listing_image__renditions", queryset=renditions_queryset)
-        )
-
-.. _image_rendition_methods:
-
-Model methods involved in rendition generation
-----------------------------------------------
-
-.. versionadded:: 3.0
-    The following method references are only applicable to Wagtail versions 3.0 and above.
-
-The following ``AbstractImage`` model methods are involved in finding and generating a renditions. If using a custom image model, you can customise the behaviour of either of these methods by overriding them on your model:
-
-.. automodule:: wagtail.images.models
-
-.. class:: AbstractImage
-    :noindex:
-
-    .. automethod:: get_rendition
-
-    .. automethod:: find_existing_rendition
-
-    .. automethod:: create_rendition
-
-    .. automethod:: generate_rendition_file