Instantly share code, notes, and snippets.
Created
April 4, 2017 08:09
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save SalahAdDin/8ba7239a2b3c263de1f57fe1fe32eb00 to your computer and use it in GitHub Desktop.
Trying to make a custom template tag.
This file contains hidden or 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 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