Skip to content

Instantly share code, notes, and snippets.

@JordanReiter
Last active April 10, 2019 15:33
Show Gist options
  • Save JordanReiter/82429200a0694a3140c7f186cd5bc926 to your computer and use it in GitHub Desktop.
Save JordanReiter/82429200a0694a3140c7f186cd5bc926 to your computer and use it in GitHub Desktop.
Django template context placeholder
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': "user@example.edu",
'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