{"result":{"depiction_url":"https:\/\/zotonic.com\/image\/2022\/9\/20\/dsc07845.jpg%28800x800%29%28upscale%29%28UXyHlE1iwy-1kuj937uiG-9fckzZB20TzWa7dV3TqAU%29.jpg","edges":{"depiction":{"objects":[{"created":"2022-09-20T12:48:59Z","object_id":{"id":2328,"is_a":["media","image"],"name":null,"title":{"_type":"trans","tr":{"en":"DSC07845.jpeg"}},"uri":"https:\/\/zotonic.com\/id\/2328"},"seq":1000000}],"predicate":{"id":304,"is_a":["meta","predicate"],"name":"depiction","title":{"_type":"trans","tr":{"nl":"Afbeelding","en":"Depiction"}},"uri":"http:\/\/xmlns.com\/foaf\/0.1\/depiction"}},"hasreference":{"objects":[{"created":"2026-10-07T11:13:43Z","object_id":{"id":1461,"is_a":["text","documentation","reference","template_filter"],"name":"doc_template_filter_filter_escape","title":"escape","uri":"https:\/\/zotonic.com\/id\/1461"},"seq":1},{"created":"2026-10-07T11:13:43Z","object_id":{"id":1536,"is_a":["text","documentation","developerguide"],"name":"doc_developerguide_access_control","title":{"_type":"trans","tr":{"en":"Keep permission checks at the boundary"}},"uri":"https:\/\/zotonic.com\/id\/1536"},"seq":2}],"predicate":{"id":2774,"is_a":["meta","predicate"],"name":"hasreference","title":{"_type":"trans","tr":{"en":"Documentation reference"}},"uri":"https:\/\/zotonic.com\/id\/hasreference"}},"refers":{"objects":[{"created":"2026-10-07T11:13:04Z","object_id":{"id":1461,"is_a":["text","documentation","reference","template_filter"],"name":"doc_template_filter_filter_escape","title":"escape","uri":"https:\/\/zotonic.com\/id\/1461"},"seq":1000000},{"created":"2026-10-07T11:13:04Z","object_id":{"id":1536,"is_a":["text","documentation","developerguide"],"name":"doc_developerguide_access_control","title":{"_type":"trans","tr":{"en":"Keep permission checks at the boundary"}},"uri":"https:\/\/zotonic.com\/id\/1536"},"seq":1000000},{"created":"2026-10-07T11:13:04Z","object_id":{"id":2960,"is_a":["text","documentation","developerguide"],"name":"developer_model_api","title":{"_type":"trans","tr":{"en":"Expose data through a model"}},"uri":"https:\/\/zotonic.com\/id\/2960"},"seq":1000000}],"predicate":{"id":2409,"is_a":["meta","predicate"],"name":"refers","title":{"_type":"trans","tr":{"en":"Refers"}},"uri":"https:\/\/zotonic.com\/id\/refers"}},"subject":{"objects":[{"created":"2026-10-07T11:13:43Z","object_id":{"id":2554,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_how_to_guide","title":"How-to guide","uri":"https:\/\/zotonic.com\/id\/2554"},"seq":1},{"created":"2026-09-14T05:48:09Z","object_id":{"id":2563,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_frontend_developer","title":"Frontend developer","uri":"https:\/\/zotonic.com\/id\/2563"},"seq":2},{"created":"2026-09-14T05:50:03Z","object_id":{"id":2620,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_template","title":"Template","uri":"https:\/\/zotonic.com\/id\/2620"},"seq":3},{"created":"2026-09-14T05:50:59Z","object_id":{"id":2685,"is_a":["categorization","keyword","keyword_quality"],"name":"zotonic_topic_security","title":"Security","uri":"https:\/\/zotonic.com\/id\/2685"},"seq":4},{"created":"2026-09-14T05:51:31Z","object_id":{"id":2672,"is_a":["categorization","keyword","keyword_technology"],"name":"zotonic_topic_html","title":"HTML","uri":"https:\/\/zotonic.com\/id\/2672"},"seq":5},{"created":"2026-09-14T05:48:06Z","object_id":{"id":2556,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_explanation","title":"Explanation","uri":"https:\/\/zotonic.com\/id\/2556"},"seq":6},{"created":"2026-09-14T05:49:20Z","object_id":{"id":2613,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_development_and_debugging","title":"Development and debugging","uri":"https:\/\/zotonic.com\/id\/2613"},"seq":7},{"created":"2026-09-14T05:50:25Z","object_id":{"id":2641,"is_a":["categorization","keyword","keyword_task"],"name":"zotonic_topic_render","title":"Render","uri":"https:\/\/zotonic.com\/id\/2641"},"seq":8},{"created":"2026-09-14T05:50:52Z","object_id":{"id":2659,"is_a":["categorization","keyword","keyword_data_type"],"name":"zotonic_topic_text","title":"Text","uri":"https:\/\/zotonic.com\/id\/2659"},"seq":9}],"predicate":{"id":308,"is_a":["meta","predicate"],"name":"subject","title":{"_type":"trans","tr":{"en":"Keyword"}},"uri":"http:\/\/purl.org\/dc\/elements\/1.1\/subject"}}},"id":2325,"is_a":["text","documentation","cookbook"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/2325"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":null,"page_url":{"en":"https:\/\/zotonic.com\/cookbook\/2325\/render-template-values-safely","x-default":"https:\/\/zotonic.com\/cookbook\/2325\/render-template-values-safely"},"preview_url":null,"resource":{"version":36,"pivot_location_lat":null,"title":{"_type":"trans","tr":{"en":"Render template values safely"}},"is_authoritative":true,"body":{"_type":"trans","tr":{"en":"<p>Template output is not universally auto-escaped. Treat request values, custom model results and external data as untrusted.<\/p>\n<p>For ordinary text and quoted HTML attributes, escape at the output:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-django\">&lt;p&gt;{{ q.search|escape }}&lt;\/p&gt;\n&lt;input name=&quot;search&quot; value=&quot;{{ q.search|escape }}&quot;&gt;\n<\/code><\/pre>\n<p>Request values can also have unexpected structured shapes. For resource lookups, resolve a scalar identifier and use <code>m.rsc[value].id<\/code>; do not trust arbitrary request data as a resource object. Check authorization on the server before reading private data or changing a resource.<\/p>\n<p>Persisted resource properties normally pass through Zotonic&#39;s resource sanitization. This allows intentional rich text such as <code>id.body<\/code> to render as HTML. That does not make every custom model, raw database value or import option safe. Do not apply an HTML-stripping bypass to untrusted content.<\/p>\n<p>JavaScript, CSS and URLs require their own handling. Prefer generated element IDs and the <code>{% javascript %}<\/code> pipeline instead of interpolating text into scripts. Use a JSON encoder when sending JSON. HTML escaping alone cannot prevent an unsafe URL scheme; accept only the schemes and destinations your feature supports.<\/p>\n<p>Test a literal <code>&lt;script&gt;<\/code> string, quotes, ampersands, unexpected list\/map input and a <code>javascript:<\/code> URL at each relevant boundary. Expect text to stay text and invalid input to be rejected. A CSP is an additional boundary, not a replacement for correct encoding and validation.<\/p>\n<h2>Display values safely<\/h2>\n<p>Resource properties read through <code>m.rsc<\/code> follow Zotonic&#39;s content handling. Query arguments and values returned by custom models do not automatically have the same guarantees.<\/p>\n<p>Escape plain text from those sources:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-django\">&lt;p&gt;{{ q.term|escape }}&lt;\/p&gt;\n<\/code><\/pre>\n<p>Do not mark arbitrary user input as safe HTML. Decide at the model or content boundary whether a field contains text, sanitized HTML, a URL, or another type. Keep that decision consistent across templates and API responses.<\/p>\n<p>When a value renders unexpectedly, inspect its type and translation behavior before applying more filters. See <a href=\"\/id\/1461\" class=\"doc-reference doc-reference-filter\"><code>filter#escape<\/code><\/a>, <a href=\"\/id\/2960\">Expose data through a model<\/a>, and <a href=\"\/id\/1536\">Keep permission checks at the boundary<\/a>.<\/p>"}},"slug":"render-template-values-safely","is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"is_featured":false,"content_group_id":{"id":339,"is_a":["meta","content_group"],"name":"default_content_group","title":{"_type":"trans","tr":{"en":"Default Content Group"}},"uri":"https:\/\/zotonic.com\/id\/default_content_group"},"category_id":{"id":318,"is_a":["meta","category"],"name":"cookbook","title":{"_type":"trans","tr":{"en":"Cookbook"}},"uri":"https:\/\/test.zotonic.com\/id\/318"},"publication_start":"2022-09-08T19:06:00Z","is_website_redirect":false,"pivot_location_lng":null,"name":null,"is_unfindable":false,"is_published":true,"doc_editorial_edges":{"depiction":[],"hasreference":[1461,1536],"subject":[2554]},"summary":{"_type":"trans","tr":{"en":"Choose escaping for the value and the output context."}},"pivot_geocode":null,"custom_slug":false,"created":"2022-09-08T19:06:30Z","uri":null,"date_is_all_day":false,"is_dependent":false,"is_page_path_multiple":false,"publication_end":"9999-08-17T12:00:00Z","modifier_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"privacy":0,"doc_editorial_bundle":true,"creator_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"seo_noindex":false,"modified":"2026-10-07T11:13:53Z","title_slug":{"_type":"trans","tr":{"en":"render-template-values-safely"}}},"uri":"https:\/\/zotonic.com\/id\/2325","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/2325"}},"status":"ok"}