forked from rc/aircox
112 lines
3.0 KiB
Python
112 lines
3.0 KiB
Python
import json
|
|
|
|
from django.db import models
|
|
from django.template.loader import render_to_string
|
|
from django.utils.safestring import mark_safe
|
|
|
|
from wagtail.core.utils import camelcase_to_underscore
|
|
|
|
|
|
class Component:
|
|
"""
|
|
A Component is a small part of a rendered web page. It can be used
|
|
to create elements configurable by users.
|
|
"""
|
|
template_name = ""
|
|
"""
|
|
[class] Template file path
|
|
"""
|
|
hide = False
|
|
"""
|
|
The component can be hidden because there is no reason to display it
|
|
(e.g. empty list)
|
|
"""
|
|
|
|
@classmethod
|
|
def snake_name(cl):
|
|
if not hasattr(cl, '_snake_name'):
|
|
cl._snake_name = camelcase_to_underscore(cl.__name__)
|
|
return cl._snake_name
|
|
|
|
def get_context(self, request, page):
|
|
"""
|
|
Context attributes:
|
|
* self: section being rendered
|
|
* page: current page being rendered
|
|
* request: request used to render the current page
|
|
|
|
Other context attributes usable in the default section template:
|
|
* content: **safe string** set as content of the section
|
|
* hide: DO NOT render the section, render only an empty string
|
|
"""
|
|
return {
|
|
'self': self,
|
|
'page': page,
|
|
'request': request,
|
|
}
|
|
|
|
def render(self, request, page, context, *args, **kwargs):
|
|
"""
|
|
Render the component. ``Page`` is the current page being
|
|
rendered.
|
|
"""
|
|
# use a different object
|
|
context_ = self.get_context(request, *args, page=page, **kwargs)
|
|
if self.hide:
|
|
return ''
|
|
|
|
if context:
|
|
context_.update({
|
|
k: v for k, v in context.items()
|
|
if k not in context_
|
|
})
|
|
|
|
context_['page'] = page
|
|
return render_to_string(self.template_name, context_)
|
|
|
|
|
|
class ExposedData:
|
|
"""
|
|
Data object that aims to be exposed to Javascript. This provides
|
|
various utilities.
|
|
"""
|
|
model = None
|
|
"""
|
|
[class attribute] Related model/class object that is to be exposed
|
|
"""
|
|
fields = {}
|
|
"""
|
|
[class attribute] Fields of the model to be exposed, as a dict of
|
|
``{ exposed_field: model_field }``
|
|
|
|
``model_field`` can either be a function(exposed, object) or a field
|
|
name.
|
|
"""
|
|
data = None
|
|
"""
|
|
Exposed data of the instance
|
|
"""
|
|
|
|
def __init__(self, object = None, **kwargs):
|
|
self.data = {}
|
|
if object:
|
|
self.from_object(object)
|
|
self.data.update(kwargs)
|
|
|
|
def from_object(self, object):
|
|
fields = type(self).fields
|
|
for k,v in fields.items():
|
|
if self.data.get(k) != None:
|
|
continue
|
|
v = v(self, object) if callable(v) else \
|
|
getattr(object, v) if hasattr(object, v) else \
|
|
None
|
|
self.data[k] = v
|
|
|
|
def to_json(self):
|
|
"""
|
|
Return a json string of encoded data.
|
|
"""
|
|
return mark_safe(json.dumps(self.data))
|
|
|