Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
    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.')
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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__()
Ejemplo n.º 8
0
def test_capitalize():
    assert capitalize('xFooBarBaz Foo oOOOo') == 'XFooBarBaz Foo oOOOo'
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
0
def test_capitalize_safetext():
    capitalized = capitalize(mark_safe('xFooBarBaz Foo oOOOo'))
    assert str(capitalized) == 'XFooBarBaz Foo oOOOo'
    assert isinstance(capitalized, SafeText)