Open Forms Client (for Django)
==============================
:Version: 0.4.0
:Source: https://github.com/open-formulieren/open-forms-client-django
:Keywords: Open Forms, Client, Django
:PythonVersion: 3.7
|build-status| |code-quality| |black| |coverage|
|python-versions| |django-versions| |pypi-version|
About
=====
Easily integrate `Open Forms`_ in your Django application. There are 3 main
features:
#. Configuration to connect to Open Forms is added to your Django admin.
#. By adding an ``OpenFormsField`` in any Django model, you get a list of forms
in Open Forms to choose from in the Django admin or other Django forms.
#. You get templatetags to render an Open Forms form in your webpage.
If you have `Sentry`_ installed and you enable Sentry in the Django admin
configuration page, it will use your existing configuration to connect to
Sentry.
|screenshot-1| |screenshot-2| |screenshot-3|
Installation
============
Requirements
------------
* Python 3.7 or newer
* Django 3.2 or newer
Install
-------
You can install Open Forms Client either via the Python Package Index (PyPI) or
from source.
To install using ``pip``:
.. code-block:: bash
pip install django-open-forms-client
Usage
=====
To use this with your project you need to follow these steps:
#. Add ``open_forms_client`` to ``INSTALLED_APPS`` in your Django project's
``settings.py``:
.. code-block:: python
INSTALLED_APPS = (
# ...,
"openformsclient",
)
#. Add an ``OpenFormsField`` to your relevant models (like a ``Page`` model):
.. code-block:: python
from openformsclient.models import OpenFormsField
class Page(models.Model):
# ...
form = OpenFormsSlugField(blank=True)
There is also a ``OpenFormsUUIDField`` that stores the UUID of the form
instead of the "slug". This is more precise but if someone replaces a form
in Open Forms, the UUID will change but the slug might remain the same.
#. Add the templatetags ``{% openforms_sdk_media %}`` and
``{% openforms_form page.form %}`` to your templates, to render an Open
Forms form:
.. code-block:: jinja
{% load openforms %}
<!-- Optional to render Open Forms in the proper language -->
<html lang="nl">
<head>
<!-- Required for icons used by Open Forms -->
<meta charset="utf-8">
{% openforms_sdk_media %}
</head>
<body>
{% if page.form %}
{% openforms_form page.form %}
{% else %}
<p>This page has no form</p>
{% endif %}
</body>
</html>
#. Configure your Open Forms connection and settings in the admin, under
**Open Forms client configuration**. Once the **status** field shows a green
icon, your configuration is working.
#. Done.
Templatetags
------------
There are 4 templatetags available with several parameters. All parameters
translate to `Open Forms SDK`_ parameters.
.. code-block:: jinja
{% load openforms %}
{% openforms_form form_id csp_nonce base_path lang html_id %}
{% openforms_sdk_media %}
{% openforms_sdk_js %}
{% openforms_sdk_css %}
Gotcha's
--------
Open Forms configuration
~~~~~~~~~~~~~~~~~~~~~~~~
Note that these are **not** settings in your own webapplication but they should
be set correctly in the Open Forms installation.
* ``ALLOWED_HOSTS`` contains your domain name.
* ``CSRF_TRUSTED_ORIGINS`` contains your domain name.
* ``CSRF_COOKIE_SAMESITE`` should be ``"none"``.
CSP headers
~~~~~~~~~~~
When your webapplication uses `CSP headers`_ you need to pass the ``csp_nonce``
to the ``openforms_form`` templatetag as well. If you use `Django-CSP`_ you can
do this:
.. code-block:: html
{% load openforms %}
{% openforms_form page.form csp_nonce=request.csp_nonce %}
Additionally, you need to allow your webapplication to load styles and scripts
from the Open Forms SDK and connect to the Open Forms API. When using
`Django-CSP`_ some options need to be changed in your ``settings.py``:
.. code-block:: python
# The Open Forms SDK files might differ from the API domain. Note that this
# the same domain as configured in the Open Forms configuration model. You
# might do something smart to use that value here.
OPEN_FORMS_API_DOMAIN = "forms.example.com"
OPEN_FORMS_SDK_DOMAIN = OPEN_FORMS_API_DOMAIN
# Allow your webapp to load styles from Open Forms SDK.
CSP_STYLE_SRC = ("'self'", OPEN_FORMS_SDK_DOMAIN)
# Allow your webapp to load script from Open Forms SDK.
CSP_SCRIPT_SRC = ("'self'", OPEN_FORMS_SDK_DOMAIN)
# Allow your webapp to load images from Open Forms SDK.
CSP_IMG_SRC = ("'self'", OPEN_FORMS_SDK_DOMAIN)
# Allow your webapp to load fonts from Open Forms SDK.
CSP_FONT_SRC = ("'self'", OPEN_FORMS_SDK_DOMAIN)
# Allow your webapp to connect to the Open Forms API.
CSP_CONNECT_SRC = ("'self'", OPEN_FORMS_API_DOMAIN)
Make page refreshes work
~~~~~~~~~~~~~~~~~~~~~~~~
The URL changes when you start a form, indicating the step you are currently
on. Refreshing the page will result in a HTTP 404 because this URL does not
actually exist. You need to catch these URL-patterns and redirect the user
back to the form. You can so like this:
.. code-block:: python
# urls.py
# The view thats starts the form
path("page/<slug:slug>", PageView.as_view(), name="page"),
# Whenever you refresh the page that has the form, the URL might be changed
# and needs to redirect the user to the start of the form.
path("page/<slug:slug>/<path:rest>", PageView.as_view()),
Form shows a CSRF error
~~~~~~~~~~~~~~~~~~~~~~~
This can have many reasons because by default, you typically don't want
cross-site requests. The whole point of this client however, is to allow
cross-site requests from your website to Open Forms.
Make sure your (not Open Forms) ``SECURE_REFERER_POLICY`` Django setting is set
to ``origin-when-cross-origin`` or less strict. In Django 3.1 this was made
more strict by default.
If this is set correctly and you still get this error, see above settings if
your Open Forms installation was correctly configured.
Form won't start
~~~~~~~~~~~~~~~~
If you can see the form startpage but when you click "start" it doesn't do
anything (or you see a CSRF error in your browser log), you are most likely
logged in to Open Forms as admin user. Log out of Open Forms or use incognito
mode to start the form.
This is a
`known issue <https://github.com/open-formulieren/open-forms/issues/2104>`_.
Licence
=======
Copyright © `Maykin Media B.V.`_, 2022
Licensed under the `MIT`_.
.. _`Maykin Media B.V.`: https://www.maykinmedia.nl
.. _`MIT`: LICENSE
.. _`Open Forms`: https://github.com/open-formulieren/open-forms
.. _`Open Forms SDK`: https://github.com/open-formulieren/open-forms-sdk
.. _`Sentry`: https://sentry.io/
.. _`CSP headers`: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
.. _`Django-CSP`: https://github.com/mozilla/django-csp
.. |build-status| image:: https://github.com/open-formulieren/open-forms-client-django/workflows/Run%20CI/badge.svg
:alt: Build status
:target: https://github.com/open-formulieren/open-forms-client-django/actions?query=workflow%3A%22Run+CI%22
.. |code-quality| image:: https://github.com/open-formulieren/open-forms-client-django/workflows/Code%20quality%20checks/badge.svg
:alt: Code quality checks
:target: https://github.com/open-formulieren/open-forms-client-django/actions?query=workflow%3A%22Code+quality+checks%22
.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
.. |coverage| image:: https://codecov.io/gh/open-formulieren/open-forms-client-django/branch/main/graph/badge.svg
:target: https://codecov.io/gh/open-formulieren/open-forms-client-django
:alt: Coverage status
.. |python-versions| image:: https://img.shields.io/pypi/pyversions/django-open-forms-client.svg
.. |django-versions| image:: https://img.shields.io/pypi/djversions/django-open-forms-client.svg
.. |pypi-version| image:: https://img.shields.io/pypi/v/django-open-forms-client.svg
:target: https://pypi.org/project/django-open-forms-client/
.. |screenshot-1| image:: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_admin_config.png
:alt: Ordered dashboard with dropdown menu.
:target: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_admin_config.png
.. |screenshot-2| image:: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_admin_model_field.png
:alt: Ordered dashboard with dropdown menu.
:target: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_admin_model_field.png
:width: 49%
.. |screenshot-3| image:: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_form_rendering.png
:alt: Ordered dashboard with dropdown menu.
:target: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_form_rendering.png
:width: 49%
Raw data
{
"_id": null,
"home_page": "https://github.com/open-formulieren/open-forms-client-django",
"name": "django-open-forms-client",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "Open Forms, Client, Django",
"author": "Maykin Media",
"author_email": "support@maykinmedia.nl",
"download_url": "https://files.pythonhosted.org/packages/d0/2a/121a69e46e0f2a709ae4cae7086018e85024b9cdbd756611c24a7fd3ef0a/django_open_forms_client-0.4.0.tar.gz",
"platform": null,
"description": "\n\nOpen Forms Client (for Django)\n==============================\n\n:Version: 0.4.0\n:Source: https://github.com/open-formulieren/open-forms-client-django\n:Keywords: Open Forms, Client, Django\n:PythonVersion: 3.7\n\n|build-status| |code-quality| |black| |coverage|\n\n|python-versions| |django-versions| |pypi-version|\n\nAbout\n=====\n\nEasily integrate `Open Forms`_ in your Django application. There are 3 main\nfeatures:\n\n#. Configuration to connect to Open Forms is added to your Django admin.\n#. By adding an ``OpenFormsField`` in any Django model, you get a list of forms\n in Open Forms to choose from in the Django admin or other Django forms.\n#. You get templatetags to render an Open Forms form in your webpage.\n\nIf you have `Sentry`_ installed and you enable Sentry in the Django admin\nconfiguration page, it will use your existing configuration to connect to\nSentry.\n\n|screenshot-1| |screenshot-2| |screenshot-3|\n\n\nInstallation\n============\n\nRequirements\n------------\n\n* Python 3.7 or newer\n* Django 3.2 or newer\n\n\nInstall\n-------\n\nYou can install Open Forms Client either via the Python Package Index (PyPI) or\nfrom source.\n\nTo install using ``pip``:\n\n.. code-block:: bash\n\n pip install django-open-forms-client\n\n\nUsage\n=====\n\nTo use this with your project you need to follow these steps:\n\n#. Add ``open_forms_client`` to ``INSTALLED_APPS`` in your Django project's\n ``settings.py``:\n\n .. code-block:: python\n\n INSTALLED_APPS = (\n # ...,\n \"openformsclient\",\n )\n\n#. Add an ``OpenFormsField`` to your relevant models (like a ``Page`` model):\n\n .. code-block:: python\n\n from openformsclient.models import OpenFormsField\n\n class Page(models.Model):\n # ...\n form = OpenFormsSlugField(blank=True)\n\n There is also a ``OpenFormsUUIDField`` that stores the UUID of the form\n instead of the \"slug\". This is more precise but if someone replaces a form\n in Open Forms, the UUID will change but the slug might remain the same.\n\n#. Add the templatetags ``{% openforms_sdk_media %}`` and\n ``{% openforms_form page.form %}`` to your templates, to render an Open\n Forms form:\n\n .. code-block:: jinja\n\n {% load openforms %}\n <!-- Optional to render Open Forms in the proper language -->\n <html lang=\"nl\">\n <head>\n <!-- Required for icons used by Open Forms -->\n <meta charset=\"utf-8\">\n\n {% openforms_sdk_media %}\n </head>\n <body>\n\n {% if page.form %}\n {% openforms_form page.form %}\n {% else %}\n <p>This page has no form</p>\n {% endif %}\n\n </body>\n </html>\n\n#. Configure your Open Forms connection and settings in the admin, under\n **Open Forms client configuration**. Once the **status** field shows a green\n icon, your configuration is working.\n\n#. Done.\n\n\nTemplatetags\n------------\n\nThere are 4 templatetags available with several parameters. All parameters\ntranslate to `Open Forms SDK`_ parameters.\n\n.. code-block:: jinja\n\n {% load openforms %}\n {% openforms_form form_id csp_nonce base_path lang html_id %}\n {% openforms_sdk_media %}\n {% openforms_sdk_js %}\n {% openforms_sdk_css %}\n\n\nGotcha's\n--------\n\nOpen Forms configuration\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nNote that these are **not** settings in your own webapplication but they should\nbe set correctly in the Open Forms installation.\n\n* ``ALLOWED_HOSTS`` contains your domain name.\n* ``CSRF_TRUSTED_ORIGINS`` contains your domain name.\n* ``CSRF_COOKIE_SAMESITE`` should be ``\"none\"``.\n\nCSP headers\n~~~~~~~~~~~\n\nWhen your webapplication uses `CSP headers`_ you need to pass the ``csp_nonce``\nto the ``openforms_form`` templatetag as well. If you use `Django-CSP`_ you can\ndo this:\n\n.. code-block:: html\n\n {% load openforms %}\n {% openforms_form page.form csp_nonce=request.csp_nonce %}\n\nAdditionally, you need to allow your webapplication to load styles and scripts\nfrom the Open Forms SDK and connect to the Open Forms API. When using\n`Django-CSP`_ some options need to be changed in your ``settings.py``:\n\n.. code-block:: python\n\n # The Open Forms SDK files might differ from the API domain. Note that this\n # the same domain as configured in the Open Forms configuration model. You\n # might do something smart to use that value here.\n OPEN_FORMS_API_DOMAIN = \"forms.example.com\"\n OPEN_FORMS_SDK_DOMAIN = OPEN_FORMS_API_DOMAIN\n\n # Allow your webapp to load styles from Open Forms SDK.\n CSP_STYLE_SRC = (\"'self'\", OPEN_FORMS_SDK_DOMAIN)\n\n # Allow your webapp to load script from Open Forms SDK.\n CSP_SCRIPT_SRC = (\"'self'\", OPEN_FORMS_SDK_DOMAIN)\n\n # Allow your webapp to load images from Open Forms SDK.\n CSP_IMG_SRC = (\"'self'\", OPEN_FORMS_SDK_DOMAIN)\n\n # Allow your webapp to load fonts from Open Forms SDK.\n CSP_FONT_SRC = (\"'self'\", OPEN_FORMS_SDK_DOMAIN)\n\n # Allow your webapp to connect to the Open Forms API.\n CSP_CONNECT_SRC = (\"'self'\", OPEN_FORMS_API_DOMAIN)\n\n\nMake page refreshes work\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe URL changes when you start a form, indicating the step you are currently\non. Refreshing the page will result in a HTTP 404 because this URL does not\nactually exist. You need to catch these URL-patterns and redirect the user\nback to the form. You can so like this:\n\n.. code-block:: python\n\n # urls.py\n\n # The view thats starts the form\n path(\"page/<slug:slug>\", PageView.as_view(), name=\"page\"),\n # Whenever you refresh the page that has the form, the URL might be changed\n # and needs to redirect the user to the start of the form.\n path(\"page/<slug:slug>/<path:rest>\", PageView.as_view()),\n\n\nForm shows a CSRF error\n~~~~~~~~~~~~~~~~~~~~~~~\n\nThis can have many reasons because by default, you typically don't want\ncross-site requests. The whole point of this client however, is to allow\ncross-site requests from your website to Open Forms.\n\nMake sure your (not Open Forms) ``SECURE_REFERER_POLICY`` Django setting is set\nto ``origin-when-cross-origin`` or less strict. In Django 3.1 this was made\nmore strict by default.\n\nIf this is set correctly and you still get this error, see above settings if\nyour Open Forms installation was correctly configured.\n\n\nForm won't start\n~~~~~~~~~~~~~~~~\n\nIf you can see the form startpage but when you click \"start\" it doesn't do\nanything (or you see a CSRF error in your browser log), you are most likely\nlogged in to Open Forms as admin user. Log out of Open Forms or use incognito\nmode to start the form.\n\nThis is a\n`known issue <https://github.com/open-formulieren/open-forms/issues/2104>`_.\n\n\nLicence\n=======\n\nCopyright \u00a9 `Maykin Media B.V.`_, 2022\n\nLicensed under the `MIT`_.\n\n.. _`Maykin Media B.V.`: https://www.maykinmedia.nl\n.. _`MIT`: LICENSE\n.. _`Open Forms`: https://github.com/open-formulieren/open-forms\n.. _`Open Forms SDK`: https://github.com/open-formulieren/open-forms-sdk\n.. _`Sentry`: https://sentry.io/\n.. _`CSP headers`: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP\n.. _`Django-CSP`: https://github.com/mozilla/django-csp\n\n.. |build-status| image:: https://github.com/open-formulieren/open-forms-client-django/workflows/Run%20CI/badge.svg\n :alt: Build status\n :target: https://github.com/open-formulieren/open-forms-client-django/actions?query=workflow%3A%22Run+CI%22\n\n.. |code-quality| image:: https://github.com/open-formulieren/open-forms-client-django/workflows/Code%20quality%20checks/badge.svg\n :alt: Code quality checks\n :target: https://github.com/open-formulieren/open-forms-client-django/actions?query=workflow%3A%22Code+quality+checks%22\n\n.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n\n.. |coverage| image:: https://codecov.io/gh/open-formulieren/open-forms-client-django/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/open-formulieren/open-forms-client-django\n :alt: Coverage status\n\n.. |python-versions| image:: https://img.shields.io/pypi/pyversions/django-open-forms-client.svg\n\n.. |django-versions| image:: https://img.shields.io/pypi/djversions/django-open-forms-client.svg\n\n.. |pypi-version| image:: https://img.shields.io/pypi/v/django-open-forms-client.svg\n :target: https://pypi.org/project/django-open-forms-client/\n\n.. |screenshot-1| image:: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_admin_config.png\n :alt: Ordered dashboard with dropdown menu.\n :target: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_admin_config.png\n\n.. |screenshot-2| image:: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_admin_model_field.png\n :alt: Ordered dashboard with dropdown menu.\n :target: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_admin_model_field.png\n :width: 49%\n\n.. |screenshot-3| image:: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_form_rendering.png\n :alt: Ordered dashboard with dropdown menu.\n :target: https://github.com/open-formulieren/open-forms-client-django/raw/main/docs/_assets/screenshot_form_rendering.png\n :width: 49%\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Easily integrate Open Forms in your Django application.",
"version": "0.4.0",
"project_urls": {
"Homepage": "https://github.com/open-formulieren/open-forms-client-django"
},
"split_keywords": [
"open forms",
" client",
" django"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "6d748cb5b97606907804167422e3890e1967e709785e2539853cc883725208c1",
"md5": "b2b22bb853c152b5d35c84f960865192",
"sha256": "bc5762c97b316ec48462882358b251478acb94e817f046f0d44265030b638013"
},
"downloads": -1,
"filename": "django_open_forms_client-0.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b2b22bb853c152b5d35c84f960865192",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 14646,
"upload_time": "2024-06-24T10:37:36",
"upload_time_iso_8601": "2024-06-24T10:37:36.584232Z",
"url": "https://files.pythonhosted.org/packages/6d/74/8cb5b97606907804167422e3890e1967e709785e2539853cc883725208c1/django_open_forms_client-0.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d02a121a69e46e0f2a709ae4cae7086018e85024b9cdbd756611c24a7fd3ef0a",
"md5": "b7c42455d27b4624ef356659eb5b23d2",
"sha256": "8319b3720ff39d6e043598ddec58d88122e797f208e730730ff221c2ab14ed79"
},
"downloads": -1,
"filename": "django_open_forms_client-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "b7c42455d27b4624ef356659eb5b23d2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 14933,
"upload_time": "2024-06-24T10:37:38",
"upload_time_iso_8601": "2024-06-24T10:37:38.220636Z",
"url": "https://files.pythonhosted.org/packages/d0/2a/121a69e46e0f2a709ae4cae7086018e85024b9cdbd756611c24a7fd3ef0a/django_open_forms_client-0.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-06-24 10:37:38",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "open-formulieren",
"github_project": "open-forms-client-django",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "django-open-forms-client"
}