Skip to content

Instantly share code, notes, and snippets.

@RoboAndie
Last active July 30, 2021 01:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RoboAndie/8ba09337eb78b5f0346094014d5ffb64 to your computer and use it in GitHub Desktop.
Save RoboAndie/8ba09337eb78b5f0346094014d5ffb64 to your computer and use it in GitHub Desktop.
Django block template tag to display a Bootstrap modal
from django import template
from django.core.exceptions import ValidationError
from django.core.validators import validate_slug
from django.template import TemplateSyntaxError
from django.template.base import token_kwargs
register = template.Library()
@register.tag
def modal(parser, token):
"""
Display a Bootstrap modal on the page containing any valid Django template code between begin and end tags.
Examples:
{% modal %}
<p>Look ma! I'm in a modal!</p>
{% footer %}
<span>That's great, son. </span><button class="btn btn-default" data-dismiss="modal">Close</button>
{% endmodal %}
{% modal %}
<form method="POST" action="">
{% csrf_token %}
{{ form }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% endmodal %}
"""
bits = token.split_contents()
bit_kwargs = token_kwargs(bits[1:], parser)
modal_id = str(bit_kwargs.get('modal_id', 'modal'))
title = str(bit_kwargs.get('title', None))
nodelist_body = parser.parse(('footer', 'endmodal'))
token = parser.next_token()
if token.contents == 'footer':
nodelist_footer = parser.parse(('endmodal',))
parser.delete_first_token()
else:
nodelist_footer = None
return ModalNode(template, modal_id, title, nodelist_body, nodelist_footer)
class ModalNode(template.Node):
def __init__(self, modal_id, title, nodelist_body, nodelist_footer):
self.modal_id = modal_id
self.title = title
self.nodelist_body = nodelist_body
self.nodelist_footer = nodelist_footer
def render(self, context):
modal_id = self.modal_id.resolve(context) if self.modal_id else 'modal'
title = self.title.resolve(context) if self.title else None
footer = f'<div class="modal-footer">{self.nodelist_footer.render(context)}</div>' if self.nodelist_footer else ''
output = \
f'<div class="modal fade" id="{self.modal_id}" tabindex="-1" role="dialog" ' \
f' aria-labelledby="{self.modal_id}-title" aria-hidden="true">' \
f' <div class="modal-dialog modal-dialog-centered" role="document">' \
' <div class="modal-content">' \
' <div class="modal-header">' \
f' <h5 class="modal-title" id="{self.modal_id}-title">{self.title}</h5>' \
' <button type="button" class="close" data-dismiss="modal" aria-label="Close">' \
' <span aria-hidden="true">&times;</span>' \
' </button>' \
' </div>' \
' <div class="modal-body">' \
f' {self.nodelist_body.render(context)}' \
' </div>' \
f' {footer}' \
' </div>' \
' </div>' \
'</div>'
return output
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment