Created
October 18, 2019 01:22
-
-
Save kyleingraham/b35a4700cfabc79fe75a6f3435032758 to your computer and use it in GitHub Desktop.
Globally Include Django CSRF Tokens in Forms When Using intercooler.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% load ic_csrf_token %} | |
{% ic_csrf_token %} | |
<label> | |
<select name="manufacturer" | |
ic-post-to="/models" | |
ic-target="#model-select" | |
ic-replace-target="true"> | |
<option disabled selected>Select a manufacturer</option> | |
<option value="Audi">Audi</option> | |
<option value="Lexus">Lexus</option> | |
<option value="Mercedes">Mercedes</option> | |
</select> | |
</label> | |
<div id="model-select"> | |
<label> | |
<select> | |
<option>---</option> | |
</select> | |
</label> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import warnings | |
from django import template | |
from django.conf import settings | |
from django.template.base import Node | |
from django.utils.html import format_html | |
register = template.Library() | |
class ICCsrfTokenNode(Node): | |
def __init__(self, ic_global_include_id: str = "csrf-token"): | |
super().__init__() | |
self._ic_global_include_id = ic_global_include_id | |
def render(self, context): | |
csrf_token = context.get("csrf_token") | |
if csrf_token: | |
if csrf_token == "NOTPROVIDED": | |
return format_html("") | |
else: | |
return format_html('<input type="hidden" id="{}" name="csrfmiddlewaretoken" ' | |
'ic-global-include="#{}" value="{}">', self._ic_global_include_id, | |
self._ic_global_include_id, csrf_token) | |
else: | |
# It's very probable that the token is missing because of | |
# misconfiguration, so we raise a warning | |
if settings.DEBUG: | |
warnings.warn( | |
"A {% ic_csrf_token %} was used in a template, but the context " | |
"did not provide the value. This is usually caused by not " | |
"using RequestContext." | |
) | |
return '' | |
@register.tag | |
def ic_csrf_token(parser, token): | |
"""An intercooler.js-compatible version of the Django csrf_token template tag. | |
When used in your template, it provides a hidden form input with the ic-global-include HTML attribute. | |
Any form present on a template that includes this tag will have Django's csrfmiddlewaretoken submitted | |
alongside any other fields it contains. | |
By default, the form's input's id and ic-global-include attributes are set to "csrf-token". To set a | |
different id, provide the id as a string to the instantiation of the ICCsrfTokenNode this function returns. | |
For example, to set the id and ic-global-include attributes to "ic-csrf-token": | |
ICCsrfTokenNode(ic_global_include_id="ic-csrf-token") | |
This tag is based on the fine work of the Django dev team. | |
""" | |
return ICCsrfTokenNode() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To use this tag, include
ic_csrf_token.py
in../[your Django app]/templatetags
(templatetags must be a valid Python package).This tag is 99% identical to the original csrf_token tag with a few key changes.