Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ [#3573] Add a new template tag as_json #3594

Merged
merged 3 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions docs/manual/forms/examples/form_with_geometry.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
.. _example_form_with_geometry:

================================================
Kaartmateriaal en registratie in de Objecten API
================================================

In dit formulier maken we gebruik van de "Kaart"-component om coördinaten van een
locatie uit te vragen en te registreren. Het formulier wordt gekoppeld met de
`Objecten API`_ voor het registreren van de inzendingsgegevens.

We gaan er van uit dat de koppeling met de Objecten API
:ref:`geconfigureerd <configuration_registration_objects>` is, en gebruiken als
objecttype-URL ``https://objecttype-example.nl/api/v2/objecttype/123``.

Formulier maken
===============

We bouwen een formulier met twee kaarten - één kaart wordt gebruikt voor "dé" geometrie
van het hele Object in de Objecten API en de andere kaart wordt als extra/vrije-vorm
attribuut meegestuurd.

#. Maak een formulier aan met de volgende gegevens:

* **Naam**: Kaartgegevens registreren in de Objecten API

#. Klik op het tabblad **Stappen en velden**.
#. Klik aan de linkerkant op **Stap toevoegen** en selecteer **Maak een nieuwe
formulierdefinitie**.
#. Onder de sectie **(Herbruikbare) stapgegevens** vul het volgende in:

* **Naam**: Kaarten

#. Scrol naar beneden en klik de sectie **Speciale velden** aan.
#. Sleep een **Kaart** component op het witte vlak en vul de volgende
gegevens in:

* **Label**: Hoofdgeometrie

#. Klik vervolgens de **Registratie** tab aan en vul de volgende gegevens in:

* **Registratie-attribuut**: Locatie > Coördinaten

#. Druk daarna op **Opslaan**.

#. Sleep een tweede **Kaart** component op het witte vlak, vul de volgende
gegevens in en druk daarna op **Opslaan**:

* **Label**: Extra geometrie

#. Klik op het tabblad **Registratie**.
#. Klik op **Registratiepluginoptie toevoegen** en vul de volgende gegevens in:

* **Naam**: Objecten API
* **Registratiemethode**: Objecten API registratie
* **Objecttype**: ``https://objecttype-example.nl/api/v2/objecttype/123``
* **JSON-inhoud sjabloon**:

.. code-block:: django

{
"extraGeometrie": {% as_geo_json variables.extraGeometrie %}
}

#. Druk daarna op **Opslaan en opnieuw bewerken**. Het formulier kan nu ingevuld en
ingestuurd worden.


.. note:: Het inrichten van het Objecttype en de Objecten API is geen onderdeel van
dit voorbeeld, maar wel essentieel om zonder fouten formulierinzendingen te kunnen
verwerken.


Toelichting
===========

De eerste kaart is ingesteld via de "Registratie" tab op het component. Dit zorgt ervoor
dat de Objecten API-registratieplugin dit veld gebruikt voor "de" geometrie van het object
in de Objecten API. Deze kent hiervoor namelijk één vast attribuut.

Echter, we kunnen extra geometrieën alsnog meesturen (als het objecttype dit modelleert),
dit doen we door het als ``GeoJSON`` te formatteren met de ``{% as_geo_json ... %}``
sjablooncode.

.. note:: Het is niet de bedoeling dat meerdere kaarten via de "Registratie" tab gekoppeld
worden aan het Locatie-attribuut - als je dit wel doet, dan zal er slechts één component
meegestuurd worden.

Het resulterende object wat naar de Objecten API gestuurd wordt ziet er uit als:

.. code-block:: json

{
"type": "https://objecttype-example.nl/api/v2/objecttype/123",
"record": {
"typeVersion": "1",
"data": {
"extraGeometrie": {
"type": "Point",
"coordinates": [52.37403, 4.88969]
}
},
"startAt": "2023-01-01",
"geometry": {
"type": "Point",
"coordinates": [51.9225, 4.47917]
}
}
}

sergei-maertens marked this conversation as resolved.
Show resolved Hide resolved
.. seealso::

De :ref:`sjabloondocumentatie <manual_templates>` heeft een referentie van beschikbare
template tags, met details voor de :ref:`objecten_api_registratie`.

.. _Objecten API: https://objects-and-objecttypes-api.readthedocs.io/
1 change: 1 addition & 0 deletions docs/manual/forms/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Voorbeelden
dynamic_options_3
service_fetch
suwinet
form_with_geometry

======================
Verouderde voorbeelden
Expand Down
5 changes: 5 additions & 0 deletions docs/manual/templates.rst
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ Voorbeeld

Mede-ondertekend door: N. Doe (BSN: 123456789)

.. _objecten_api_registratie:

Objecten API registratie
========================
Expand All @@ -471,6 +472,9 @@ alle gegevens uit het formulier en de waarden ingevuld door de gebruiker.
``{{ voornaam }}``. Echter, in de sjablonen voor de Objecten API dient u deze als ``variables.<variabele>`` te refereren,
bijvoorbeeld ``{{ variables.voornaam }}``. Dit zal in de toekomst voor alle sjablonen gelden.

.. seealso ::

See :ref:`example_form_with_geometry` for a more detailed example.

**Speciale instructies**

Expand All @@ -489,6 +493,7 @@ Variabele Beschrijving
``{{ submission.csv_url }}`` De URL van het inzendingsrapport (in CSV formaat) in de documenten API. Dit document is mogelijk niet aangemaakt
``{% json_summary %}`` JSON met ``"<variabele-eigenschapsnaam>": "<waarde>"`` van alle formuliervelden.
``{% uploaded_attachment_urls %}`` Een lijst met de URLs van documenten toegevoegd door de inzender. De URLs verwijzen naar het geregistreerde document in de Documenten API.
``{% as_geo_json variables.map %}`` Sluit de gerefereerde variabele (`variables.map`) in als JSON.
===================================== ===========================================================================


Expand Down
1 change: 1 addition & 0 deletions src/openforms/forms/models/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Form(models.Model):
product = models.ForeignKey(
"products.Product", null=True, blank=True, on_delete=models.CASCADE
)

category = models.ForeignKey(
"forms.Category", null=True, blank=True, on_delete=models.PROTECT
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,40 @@


@register.simple_tag(takes_context=True)
def uploaded_attachment_urls(context):
def uploaded_attachment_urls(context: template.Context) -> SafeString:
"""
Output a sequence of attachment URLs as a JSON-serialized list.
"""
# attachments is a list of URLs
attachments = context.get("submission", {}).get("uploaded_attachment_urls", [])
return SafeString(json.dumps(attachments))


@register.simple_tag(takes_context=True)
def json_summary(context):
def json_summary(context: template.Context) -> SafeString:
submission = context.get("_submission")
if not submission:
return {}

json_data = render_json(submission)
json_data = render_json(submission) if submission else {}

if settings.ESCAPE_REGISTRATION_OUTPUT:
json_data = html_escape_json(json_data)

return SafeString(json.dumps(json_data))


@register.simple_tag
def as_geo_json(value: list[float] | str) -> SafeString:
"""Output the ``value`` as a safe GeoJSON dumped string.

As of today, this only supports coordinates. This essentially does the same thing as
:func:`_transform_coordinates`, but for any map component.
"""
data = (
{
"type": "Point",
"coordinates": [value[0], value[1]],
}
if value
else {}
)

return SafeString(json.dumps(data))
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,29 @@ def test_render_json_summary_no_submission(self):
)

self.assertEqual(rendered, "{}")


class AsGeoJsonTests(TestCase):
def test_render_as_geo_json(self):
Viicos marked this conversation as resolved.
Show resolved Hide resolved
rendered = render_from_string(
"{% as_geo_json variables.0.value %}",
context={"variables": [{"value": [1.0, 2.0]}]},
backend=openforms_backend,
disable_autoescape=True,
)

expected = '{"type": "Point", "coordinates": [1.0, 2.0]}'

self.assertEqual(rendered, expected)

def test_render_as_geo_json_no_value(self):
rendered = render_from_string(
"{% as_geo_json variables.0.value %}",
context={"variables": [{"value": ""}]},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked on our test environment and no value currently indeed presents itself as an empty string.

Which is weird, null would make more sense but that's the scope for a different ticket... 🤔

backend=openforms_backend,
disable_autoescape=True,
)

expected = "{}"

self.assertEqual(rendered, expected)
Loading