def evaluate_attrs(obj, **kwargs): attrs = obj.attrs or {} # Micro optimization from iommi.debug import iommi_debug_on if not attrs and not iommi_debug_on(): return '' return Attrs( obj, **{ 'class': { k: evaluate_strict(v, **kwargs) for k, v in items( evaluate_strict(attrs.get('class', {}), **kwargs)) } }, style={ k: evaluate_strict(v, **kwargs) for k, v in items(evaluate_strict(attrs.get('style', {}), ** kwargs)) }, **{ k: evaluate_strict(v, **kwargs) for k, v in items(attrs) if k not in ('class', 'style') }, )
def __init__(self, *, endpoints: Dict[str, Any] = None, include, **kwargs): super(Part, self).__init__(include=include, **kwargs) collect_members(self, name='endpoints', items=endpoints, cls=Endpoint) if iommi_debug_on(): import inspect self._instantiated_at_frame = inspect.currentframe().f_back
def __init__(self, *bases, base_template=None, content_block=None, assets=None, root=None, internal=False, **kwargs): self.name = None self.internal = internal self.base_template = base_template if not self.base_template: for base in reversed(bases): if base.base_template: self.base_template = base.base_template break self.content_block = content_block if not self.content_block: for base in reversed(bases): if base.content_block: self.content_block = base.content_block break if assets: from iommi.debug import iommi_debug_on if iommi_debug_on(): print("Warning: The preferred way to add top level assets config to a Style is via the root argument. " "I.e. assets__* becomes root__assets__*") setdefaults_path(root, assets=assets) self.root = {k: v for k, v in items(Namespace(*(base.root for base in bases), root)) if v is not None} self.config = Namespace(*[x.config for x in bases], recursive_namespace(kwargs))
def render_root(*, part, template_name=MISSING, content_block_name=MISSING, context, **render): assert part._is_bound if template_name is MISSING: template_name = getattr(settings, 'IOMMI_BASE_TEMPLATE', DEFAULT_BASE_TEMPLATE) try: get_template(template_name) except TemplateDoesNotExist: template_name = f'iommi/base_{get_style_for(part)}.html' if content_block_name is MISSING: content_block_name = getattr(settings, 'IOMMI_CONTENT_BLOCK', DEFAULT_CONTENT_BLOCK) title = getattr(part, 'title', '') from iommi.debug import iommi_debug_panel from iommi import Page context = dict( content=part.__html__(**render), title=title if title not in (None, MISSING) else '', iommi_debug_panel=iommi_debug_panel(part) if iommi_debug_on() else '', **(part.context if isinstance(part, Page) else {}), **context, ) template_string = '{% extends "' + template_name + '" %} {% block ' + content_block_name + ' %}{{ iommi_debug_panel }}{{ content }}{% endblock %}' return get_template_from_string(template_string).render( context=context, request=part.get_request())
def __init__(self, parent, **attrs): from iommi.debug import iommi_debug_on if iommi_debug_on() and getattr(parent, '_name', None) is not None: attrs['data-iommi-path'] = parent.iommi_dunder_path attrs['data-iommi-type'] = type(parent).__name__ super(Attrs, self).__init__(attrs)
def on_bind(self) -> None: if self.attr is MISSING: self.attr = self._name # Not strict evaluate on purpose self.model = evaluate(self.model, **self.iommi_evaluate_parameters()) if self.model and self.include: try: self.search_fields = get_search_fields(model=self.model) except NoRegisteredSearchFieldException: self.search_fields = ['pk'] if iommi_debug_on(): print(f'Warning: falling back to primary key as lookup and sorting on {self._name}. \nTo get rid of this warning and get a nicer lookup and sorting use register_search_fields.')
def evaluate_attrs(obj, **kwargs): attrs = obj.attrs or {} # Micro optimization from iommi.debug import iommi_debug_on if not attrs and not iommi_debug_on(): return '' classes = evaluate_strict(attrs.get('class', {}), **kwargs) assert not isinstance( classes, str ), """CSS classes needs to be specified as dicts, not as strings. So you want something like: field__class__foo=True or field__class={'foo-bar': true}""" styles = evaluate_strict(attrs.get('style', {}), **kwargs) assert not isinstance( styles, str ), """CSS styles needs to be specified as dicts, not as strings. So you want something like: field__style__display='none' or field__style={'background-color': 'blue'}""" return Attrs( obj, **{ 'class': {k: evaluate_strict(v, **kwargs) for k, v in items(classes)} }, style={k: evaluate_strict(v, **kwargs) for k, v in items(styles)}, **{ k: evaluate_strict(v, **kwargs) for k, v in items(attrs) if k not in ('class', 'style') }, )
def on_bind(self) -> None: assert self.template form = self.iommi_parent().iommi_parent() if self.attr is MISSING: self.attr = self._name if self.display_name is MISSING: self.display_name = capitalize(self._name).replace('_', ' ') if self._name else '' self.errors = Errors(parent=self, **self.errors) if form.editable is False: self.editable = False # Not strict evaluate on purpose self.model = evaluate(self.model, **self.iommi_evaluate_parameters()) self.choices = evaluate_strict(self.choices, **self.iommi_evaluate_parameters()) self.initial = evaluate_strict(self.initial, **self.iommi_evaluate_parameters()) self._read_initial() self._read_raw_data() self.parsed_data = evaluate_strict(self.parsed_data, **self.iommi_evaluate_parameters()) self._parse() self._validate() self.input = self.input.bind(parent=self) self.label = self.label.bind(parent=self) assert not self.label.children self.label.children = dict(text=evaluate_strict(self.display_name, **self.iommi_evaluate_parameters())) self.non_editable_input = self.non_editable_input.bind(parent=self) if self.model and self.include: try: self.search_fields = get_search_fields(model=self.model) except NoRegisteredSearchFieldException: self.search_fields = ['pk'] if iommi_debug_on(): print(f'Warning: falling back to primary key as lookup and sorting on {self._name}. \nTo get rid of this warning and get a nicer lookup and sorting use register_search_fields.')
def render_root(*, part, context, **render): assert part._is_bound root_style_name = get_iommi_style_name(part) root_style = get_style(root_style_name) template_name = root_style.base_template content_block_name = root_style.content_block # Render early so that all the binds are forced before we look at all_assets, # since they are populated as a side-effect content = part.__html__(**render) assets = part.iommi_collected_assets() assert template_name, f"{root_style_name} doesn't have a base_template defined" assert content_block_name, f"{root_style_name} doesn't have a content_block defined" title = get_title(part) from iommi.debug import iommi_debug_panel from iommi import Page from iommi.fragment import Container context = dict( container=Container(_name='Container').bind(parent=part), content=content, title=title if title not in (None, MISSING) else '', iommi_debug_panel=iommi_debug_panel(part) if iommi_debug_on() and '_iommi_disable_debug_panel' not in part.get_request().GET else '', assets=assets, **(part.context if isinstance(part, Page) else {}), **context, ) template_string = ('{% extends "' + template_name + '" %} {% block ' + content_block_name + ' %}{{ iommi_debug_panel }}{{ content }}{% endblock %}') return get_template_from_string(template_string).render( context=context, request=part.get_request())
def render_root(*, part, context, **render): assert part._is_bound root_style_name = get_style_name_for(part) root_style = get_style(root_style_name) template_name = root_style.base_template content_block_name = root_style.content_block assert template_name, f"{root_style_name} doesn't have a base_template defined" assert content_block_name, f"{root_style_name} doesn't have a content_block defined" title = getattr(part, 'title', None) if title is None: parts = getattr(part, 'parts', None) if parts is not None: for p in parts.values(): title = getattr(p, 'title', None) if title is not None: break from iommi.debug import iommi_debug_panel from iommi import Page from iommi.fragment import Container context = dict( container=Container(_name='Container').bind(parent=part), content=part.__html__(**render), title=title if title not in (None, MISSING) else '', iommi_debug_panel=iommi_debug_panel(part) if iommi_debug_on() else '', **(part.context if isinstance(part, Page) else {}), **context, ) template_string = '{% extends "' + template_name + '" %} {% block ' + content_block_name + ' %}{{ iommi_debug_panel }}{{ content }}{% endblock %}' return get_template_from_string(template_string).render( context=context, request=part.get_request())
attrs__src= 'https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js', ), select2_css=Asset.css(attrs=dict( href= 'https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css', )), ) base = Style( internal=True, base_template='iommi/base.html', content_block='content', root=dict( endpoints__debug_tree=dict( include=lambda endpoint, **_: iommi_debug_on(), func=endpoint__debug_tree, ), assets=dict( jquery=Asset.js( attrs=dict( src='https://code.jquery.com/jquery-3.4.1.js', integrity= 'sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=', crossorigin='anonymous', ), after=-1, ), axios=Asset.js( attrs=dict( src=
class Page(Part): title: str = EvaluatedRefinable() member_class: Type[Fragment] = Refinable() context = Refinable( ) # context is evaluated, but in a special way so gets no EvaluatedRefinable type class Meta: member_class = Fragment @reinvokable @dispatch( parts=EMPTY, endpoints__debug_tree=Namespace( include=lambda endpoint, **_: iommi_debug_on(), func=endpoint__debug_tree, ), context=EMPTY, ) def __init__(self, *, _parts_dict: Dict[str, PartType] = None, parts: dict, **kwargs): super(Page, self).__init__(**kwargs) self.parts = { } # This is just so that the repr can survive if it gets triggered before parts is set properly # First we have to up sample parts that aren't Part into Fragment def as_fragment_if_needed(k, v): if not isinstance(v, (dict, Traversable)): return Fragment(children__text=v, _name=k) else: return v _parts_dict = { k: as_fragment_if_needed(k, v) for k, v in items(_parts_dict) } parts = Namespace( {k: as_fragment_if_needed(k, v) for k, v in items(parts)}) collect_members(self, name='parts', items=parts, items_dict=_parts_dict, cls=self.get_meta().member_class) def on_bind(self) -> None: bind_members(self, name='parts') if self.context and self.iommi_parent() != None: assert False, 'context is only valid on the root page' def own_evaluate_parameters(self): return dict(page=self) @dispatch(render=lambda rendered: format_html('{}' * len(rendered), *values(rendered))) def __html__(self, *, render=None): self.context = evaluate_strict_container( self.context or {}, **self.iommi_evaluate_parameters()) rendered = { name: as_html(request=self.get_request(), part=part, context=self.iommi_evaluate_parameters()) for name, part in items(self.parts) } return render(rendered) def as_view(self): return build_as_view_wrapper(self)