Skip to content

Instantly share code, notes, and snippets.

@SalahAdDin
Created April 4, 2017 08:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SalahAdDin/8ba7239a2b3c263de1f57fe1fe32eb00 to your computer and use it in GitHub Desktop.
Save SalahAdDin/8ba7239a2b3c263de1f57fe1fe32eb00 to your computer and use it in GitHub Desktop.
Trying to make a custom template tag.
import logging
import re
import requests
from django.conf import settings
from django.template import Library
from django.template import Node
from django.template import TemplateSyntaxError
from django.utils.html import format_html_join
from django.utils.safestring import mark_safe
from django.utils.encoding import smart_str
from wagtailgmaps.edit_handlers import random_string
register = Library()
logger = logging.getLogger(__name__)
@register.assignment_tag
def load_gmaps():
"""
Load Google Maps API using the API Key.
:return:
script_link: Properly formatted script link.
"""
js_files = [
'https://maps.googleapis.com/maps/api/js?key={}'.format(settings.WAGTAIL_ADDRESS_MAP_KEY),
'{}wagtailgmaps/js/map-field-panel.js'.format(settings.STATIC_URL),
]
js_includes = format_html_join(
'\n',
'<script type="text/javascript" src="{}"></script>',
((filename,) for filename in js_files)
)
return js_includes
# TODO: Revisar la forma correcta de implementar esto para usar en las plantillas
@register.tag('gmap')
class GMapNode(Node):
"""
Template tag ``gmap``.
Usage (shortcut):
.. code-block:: html+django
{% gmap ADDRESS [ZOOM] [SIZE] [key1=value1, key2=value2...] %}
Or as a block:
.. code-block:: html+django
{% gmap ADDRESS [SIZE] [key1=value1, key2=value2...] as VAR %}
...
{% endgmap %}
Examples:
.. code-block:: html+django
{% gmpa item.gmap %}
{% gmap item.gmap "large" %}
{% gmap item.gmap "340x200" %}
"""
error_msg = 'Syntax error. Expected: ``{% gmap ADDRESS ' \
'[size] [key1=val1 key2=val2 ...] [as var] %}``'
default_size = 'small'
default_zoom = 8
re_size = re.compile('[\'"]?(?P<width>\d+%?) *x *(?P<height>\d+%?)[\'"]?')
def __init__(self, parser, token):
"""
:param parser: Django template parser
:type parser: django.template.base.Parser
:param token: Django template token
:type token: django.template.base.Token
"""
self.parser = parser
self.bits = list(token.split_contents())
self.tag_name = str(self.pop_bit())
self.address = self.pop_bit()
if len(self.bits) > 1 and self.bits[-2] == 'as':
del self.bits[-2]
self.variable_name = str(self.pop_bit(-1))
self.nodelist_file = parser.parse(('end' + self.tag_name,))
parser.delete_first_token()
else:
self.variable_name = None
self.size = self.pop_bit() if self.bits and '=' not in self.bits[0] else None
self.options = self.parse_options(self.bits)
def render(self, context):
"""
Returns generated HTML.
:param context: Django template RequestContext
:type context: django.template.RequestContext
:return: Rendered HTML with embed video.
:rtype: django.utils.safestring.SafeText | str
"""
if (self.centre is None) or (self.centre == ''):
try:
self.centre = settings.WAGTAIL_ADDRESS_MAP_CENTER
except AttributeError:
pass
map_id = random_string()
if self.zoom is None:
try:
self.zoom = zoom
except AttributeError:
self.zoom = 8
try:
apikey = settings.WAGTAIL_ADDRESS_MAP_KEY
except AttributeError:
raise Exception('Google Maps API key is missing from settings')
self.address = self.address.resolve(context)
size = self.size.resolve(context) if self.size else None
# options = self.resolve_options(context)
try:
width, height = cls.get_size(size)
except AttributeError:
width = 100
height = 300
try:
self.units = units
except AttributeError:
self.units = 'px'
try:
# return self.render_block(context)
return '''
<div id="map-canvas-{0}" {% if width %}style="width: {1}{2}; height: {3}{2};"{% endif %} class="map-googlemap">
<noscript>
<img src="https://maps.google.com/maps/api/staticmap?center={4}&zoom={5}&size={1}x{3}&sensor=false">
</noscript>
</div>
'''.format(map_id, self.width, self.units, self.height, self.address, self.zoom)
except requests.Timeout:
logger.exception('Timeout reached during rendering Google Map (`{0}`)'.format(self.address))
return ''
def render_block(self, context):
"""
:param context: Django template RequestContext
:type context: django.template.RequestContext
:rtype: django.utils.safestring.SafeText
"""
context.push()
output = self.nodelist_file.render(context)
context.pop()
return output
@classmethod
def map(cls, url, size, context=None, **options):
"""
Direct render of embed video.
:param url: URL to embed video
:type url: str
:param size: Size of rendered block
:type size: str
:param context: Django template RequestContext
:type context: django.template.RequestContext | None
"""
return mark_safe(backend.get_embed_code(width=width, height=height))
@classmethod
def get_size(cls, value):
"""
Predefined sizes:
======== ======== =========
size width height
======== ======== =========
tiny 420 315
small 480 360
medium 640 480
large 960 720
huge 1280 960
======== ======== =========
You can also use custom size - in format ``WIDTHxHEIGHT``
(eg. ``500x400``).
:type value: str
:return: Returns tuple with (width, height) values.
:rtype: tuple[int, int]
"""
sizes = {
'tiny': (420, 315),
'small': (480, 360),
'medium': (640, 480),
'large': (960, 720),
'huge': (1280, 960),
}
value = value or cls.default_size
if value in sizes:
return sizes[value]
try:
size = cls.re_size.match(value)
return size.group('width'), size.group('height')
except AttributeError:
raise TemplateSyntaxError(
'Incorrect size.\nPossible format is WIDTHxHEIGHT or using '
'predefined size ({sizes}).'.format(sizes=', '.join(sizes.keys()))
)
def __iter__(self):
for node in self.nodelist_file:
yield node
def __repr__(self):
return '<GMapNode "%s">' % self.address
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment