def base_defaults_factory(model_field): from iommi.base import capitalize r = {} if hasattr(model_field, 'verbose_name'): r['display_name'] = capitalize(model_field.verbose_name) return r
def on_bind(self) -> None: assert self.actions_template self._valid = None request = self.get_request() self._request_data = request_data(request) self.title = evaluate_strict(self.title, **self.iommi_evaluate_parameters()) if isinstance(self.h_tag, Namespace): if self.title not in (None, MISSING): self.h_tag = self.h_tag( _name='h_tag', children__text=capitalize(self.title), ).bind(parent=self) else: self.h_tag = '' else: self.h_tag = self.h_tag.bind(parent=self) # Actions have to be bound first because is_target() needs it bind_members(self, name='actions', cls=Actions) if self._request_data is not None and self.is_target(): self.mode = FULL_FORM_FROM_REQUEST bind_members(self, name='fields') bind_members(self, name='endpoints') self.is_valid() self.errors = Errors(parent=self, errors=self.errors)
def build_and_bind_h_tag(p): if isinstance(p.h_tag, Namespace): if p.title not in (None, MISSING): p.h_tag = p.h_tag( _name='h_tag', children__text=capitalize( evaluate_strict( p.title, **p.iommi_evaluate_parameters()))).bind(parent=p) else: p.h_tag = '' else: p.h_tag = p.h_tag.bind(parent=p)
def field_defaults_factory(model_field): from iommi.base import capitalize from django.db.models import BooleanField r = {} if hasattr(model_field, 'verbose_name'): r['display_name'] = capitalize(model_field.verbose_name) if hasattr(model_field, 'null') and not isinstance(model_field, BooleanField): r['required'] = not model_field.null and not model_field.blank if hasattr(model_field, 'null'): r['parse_empty_string_as_none'] = model_field.null return r
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.')
class Action(Fragment): """ The `Action` class describes buttons and links. Examples: .. code:: python # Link Action(attrs__href='http://example.com') # Link with icon Action.icon('edit', attrs__href="edit/") # Button Action.button(display_name='Button title!') # A submit button Action.submit(display_name='Do this') # The primary submit button on a form. Action.primary() # Notice that because forms # with a single primary submit button are so common, iommi assumes # that if you have a action called submit and do NOT explicitly # specify the action that it is a primary action. This is only # done for the action called submit, inside the Forms actions # Namespace. # # For that reason this works: class MyForm(Form): class Meta: @staticmethod def actions__submit__post_handler(form, **_): if not form.is_valid(): return ... # and is roughly equivalent to def on_submit(form, **_): if not form.is_valid(): return class MyOtherForm(Form): class Meta: actions__submit = Action.primary(post_handler=on_submit) .. test r = req('post', **{'-submit': ''}) MyForm().bind(request=r).render_to_response() MyOtherForm().bind(request=r).render_to_response() """ group: str = EvaluatedRefinable() display_name: str = EvaluatedRefinable() post_handler: Callable = Refinable() @dispatch( tag='a', attrs=EMPTY, children=EMPTY, display_name=lambda action, **_: capitalize(action._name).replace( '_', ' '), ) @reinvokable def __init__(self, *, tag=None, attrs=None, children=None, display_name=None, **kwargs): if tag == 'input': if display_name and 'value' not in attrs: attrs.value = display_name else: children['text'] = display_name if tag == 'button' and 'value' in attrs: assert False, 'You passed attrs__value, but you should pass display_name' super().__init__(tag=tag, attrs=attrs, children=children, display_name=display_name, **kwargs) def on_bind(self): super().on_bind() def own_evaluate_parameters(self): return dict(action=self) def __repr__(self): return Part.__repr__(self) def own_target_marker(self): return f'-{self.iommi_path}' def is_target(self): return self.own_target_marker() in self.iommi_parent().iommi_parent( )._request_data @classmethod @class_shortcut( tag='button', ) def button(cls, call_target=None, **kwargs): return call_target(**kwargs) @classmethod @class_shortcut( call_target__attribute='button', attrs__accesskey='s', attrs__name=lambda action, **_: action.own_target_marker(), display_name=gettext_lazy('Submit'), ) def submit(cls, call_target=None, **kwargs): return call_target(**kwargs) @classmethod @class_shortcut( call_target__attribute='submit', ) def primary(cls, call_target=None, **kwargs): return call_target(**kwargs) @classmethod @class_shortcut( call_target__attribute='submit', ) def delete(cls, call_target=None, **kwargs): return call_target(**kwargs) @classmethod @class_shortcut( icon_classes=[], ) def icon(cls, icon, *, display_name=None, call_target=None, icon_classes=None, **kwargs): icon_classes_str = ' '.join( ['fa-' + icon_class for icon_class in icon_classes]) if icon_classes else '' if icon_classes_str: icon_classes_str = ' ' + icon_classes_str setdefaults_path( kwargs, display_name=format_html('<i class="fa fa-{}{}"></i> {}', icon, icon_classes_str, display_name), ) return call_target(**kwargs)
class MenuItem(MenuBase): """ Class that is used for the clickable menu items in a menu. See :doc:`Menu` for more complete examples. """ display_name: str = EvaluatedRefinable() url: str = Refinable( ) # attrs is evaluated, but in a special way so gets no EvaluatedRefinable type regex: str = EvaluatedRefinable() group: str = EvaluatedRefinable() a = Refinable() active_class = Refinable() @reinvokable @dispatch( display_name=lambda menu_item, **_: capitalize(menu_item.iommi_name()). replace('_', ' '), regex=lambda menu_item, **_: '^' + menu_item.url if menu_item.url else None, url=lambda menu_item, **_: '/' + path_join( getattr(menu_item.iommi_parent(), 'url', None), menu_item.iommi_name()) + '/', a=EMPTY, ) def __init__(self, **kwargs): super(MenuItem, self).__init__(**kwargs) def on_bind(self): super(MenuItem, self).on_bind() self.url = evaluate_strict(self.url, **self.iommi_evaluate_parameters()) # If this is a section header, and all sub-parts are hidden, hide myself if not self.url and self.sub_menu is not None and not self.sub_menu: self.include = False def own_evaluate_parameters(self): return dict(menu_item=self) def __repr__(self): r = f'{self._name} -> {self.url}' if self.sub_menu: for items in values(self.sub_menu): r += ''.join([f'\n {x}' for x in repr(items).split('\n')]) return r def __html__(self, *, render=None): a = setdefaults_path( Namespace(), self.a, children__text=self.display_name, attrs__href=self.url, _name='a', ) if self._active: setdefaults_path( a, attrs__class={self.active_class: True}, ) if self.url is None and a.tag == 'a': a.tag = None fragment = Fragment( children__a=a, tag=self.tag, template=self.template, attrs=self.attrs, _name='fragment', ) fragment = fragment.bind(parent=self) # need to do this here because otherwise the sub menu will get get double bind for name, item in items(self.sub_menu): assert name not in fragment.children fragment.children[name] = item return fragment.__html__()
def test_capitalize(): assert capitalize('xFooBarBaz Foo oOOOo') == 'XFooBarBaz Foo oOOOo'
class Action(Fragment): """ The `Action` class describes buttons and links. Examples: .. code:: python # Link Action(attrs__href='http://example.com') # Link with icon Action.icon('edit', attrs__href="edit/") # Button Action.button(attrs__value='Button title!') # A submit button Action.submit(display_name='Do this') # The primary submit button on a form, unnecessary # most of the time as a form includes a submit # button by default. Action.primary() # A button styled as primary but not using # the submit html element, but the button # element. Action.primary(call_target__attribute='button') """ group: str = EvaluatedRefinable() display_name: str = EvaluatedRefinable() post_handler: Callable = Refinable() @dispatch( tag='a', attrs=EMPTY, children=EMPTY, display_name=lambda action, **_: capitalize(action._name).replace( '_', ' '), ) @reinvokable def __init__(self, *, tag=None, attrs=None, children=None, display_name=None, **kwargs): if tag == 'input': if display_name and 'value' not in attrs: attrs.value = display_name else: children['text'] = display_name super().__init__(tag=tag, attrs=attrs, children=children, display_name=display_name, **kwargs) def on_bind(self): super().on_bind() def own_evaluate_parameters(self): return dict(action=self) def __repr__(self): return Part.__repr__(self) def own_target_marker(self): return f'-{self.iommi_path}' def is_target(self): return self.own_target_marker() in self.iommi_parent().iommi_parent( )._request_data @classmethod @class_shortcut( tag='button', ) def button(cls, call_target=None, **kwargs): return call_target(**kwargs) @classmethod @class_shortcut( call_target__attribute='button', tag='input', attrs__type='submit', attrs__accesskey='s', attrs__name=lambda action, **_: action.own_target_marker(), display_name=gettext_lazy('Submit'), ) def submit(cls, call_target=None, **kwargs): return call_target(**kwargs) @classmethod @class_shortcut( call_target__attribute='submit', ) def primary(cls, call_target=None, **kwargs): return call_target(**kwargs) @classmethod @class_shortcut( call_target__attribute='submit', ) def delete(cls, call_target=None, **kwargs): return call_target(**kwargs) @classmethod @class_shortcut( icon_classes=[], ) def icon(cls, icon, *, display_name=None, call_target=None, icon_classes=None, **kwargs): icon_classes_str = ' '.join( ['fa-' + icon_class for icon_class in icon_classes]) if icon_classes else '' if icon_classes_str: icon_classes_str = ' ' + icon_classes_str setdefaults_path( kwargs, display_name=format_html('<i class="fa fa-{}{}"></i> {}', icon, icon_classes_str, display_name), ) return call_target(**kwargs)
def test_capitalize_safetext(): capitalized = capitalize(mark_safe('xFooBarBaz Foo oOOOo')) assert str(capitalized) == 'XFooBarBaz Foo oOOOo' assert isinstance(capitalized, SafeText)