Last active
April 10, 2019 15:33
-
-
Save JordanReiter/82429200a0694a3140c7f186cd5bc926 to your computer and use it in GitHub Desktop.
Django template context placeholder
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 uuid | |
import datetime | |
import itertools | |
import re | |
import inflection # requires python library inflection (pip install inflection) | |
class ContextPlaceholder: | |
counter = itertools.count() | |
DEFAULT_VALUES = { | |
'pk': lambda: next(ContextPlaceholder.counter), | |
'id': lambda: next(ContextPlaceholder.counter), | |
'date': datetime.date.today, | |
'time': datetime.datetime.now, | |
'email': "[email protected]", | |
'uuid': uuid.uuid4, | |
'uid': uuid.uuid4, | |
'guid': uuid.uuid4, | |
} | |
CHILD_VALUES = [ | |
'capitalize', | |
'lower', | |
'strip', | |
'title', | |
'upper', | |
] | |
def __init__(self, label, parent_label=None, length=3, **extra): | |
self.label = label | |
self.singular_label = inflection.singularize(label) | |
self.parent_label = parent_label | |
self.length = length | |
self.ctx = dict(self.DEFAULT_VALUES) | |
self.ctx.update({k:v for k, v in extra.items() if v}) | |
def __repr__(self): | |
return '<{}{} (as ContextPlaceHolder)>'.format( | |
inflection.camelize(self.parent_label) + ':' if self.parent_label else '', | |
inflection.camelize(self.label) | |
) | |
def __str__(self): | |
if self.label in self.CHILD_VALUES and self.parent_label: | |
return getattr(inflection.camelize(str(self.parent_label)), self.label)() | |
return inflection.camelize(str(self.label)) | |
def __iter__(self): | |
return iter( | |
ContextPlaceholder('{}_{}'.format(self.singular_label, idx), parent_label=self.label, length=self.length, **self.ctx) | |
for idx in range(self.length) | |
) | |
def items(self): | |
return zip(self.keys(), self.values()) | |
def keys(self): | |
return ['{}_{}'.format(self.singular_label, idx) for idx in range(self.length)] | |
def values(self): | |
return [ContextPlaceholder('{}_{}'.format(self.singular_label, idx), parent_label=self.label, length=self.length, **self.ctx) for idx in range(self.length)] | |
def __getitem__(self, idx): | |
if isinstance(idx, slice): | |
return list(self)[idx] | |
try: | |
idx = int(idx) | |
except (TypeError, ValueError): | |
pass | |
try: | |
return self.get_existing_value(idx) | |
except KeyError: | |
pass | |
return ContextPlaceholder('{}_{}'.format(self.singular_label, idx), parent_label=self.label, length=self.length, **self.ctx) | |
def __call__(self, *args, **kwargs): | |
all_ctx = dict(self.ctx.items()) | |
all_ctx.update(kwargs) | |
each_label = self.singular_label | |
if self.label in self.CHILD_VALUES: | |
return getattr(inflection.camelize(str(self.parent_label)), self.label)() | |
return ContextPlaceholder('{}_instance'.format(self.singular_label), parent_label=self.label, **all_ctx) | |
def __getattr__(self, key): | |
return self.get_value(key) | |
def get_existing_value(self, key): | |
val = self.ctx[key] | |
if callable(val): | |
try: | |
return val() | |
except Exception as err: | |
pass | |
return val | |
def get_value(self, label): | |
try: | |
return self.get_existing_value(label) | |
except KeyError: | |
pass | |
if 'date_' in label or '_date' in label: | |
return self.get_existing_value('date') | |
if 'time_' in label or '_time' in label: | |
return self.get_existing_value('time') | |
if label in ('slug'): | |
return inflection.dasherize(self.label) | |
if label in ('url'): | |
return 'https://example.com/{}{}'.format( | |
re.sub(r'[_\W]+', '/', self.parent_label) + '/' if self.parent_label else '', | |
re.sub(r'[_\W]+', '/', self.label) | |
) | |
if label in ('all', 'filter'): | |
label = self.singular_label | |
return ContextPlaceholder(label, parent_label=self.label, length=self.length, **self.ctx) | |
def __len__(self): | |
return self.length |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment