class IndexPage(Page): header = Header('iommi examples') form_header = Header('Form examples') # We can create html fragments... f_a_1 = html.a('Example 1: echo submitted data', attrs__href="form_example_1/") f_b_1 = html.br() f_a_2 = html.a('Example 2: create a Foo', attrs__href="form_example_2/") f_b_2 = html.br() f_a_3 = html.a('Example 3: edit a Foo', attrs__href="form_example_3/") f_b_3 = html.br() f_a_4 = html.a('Example 4: custom buttons', attrs__href="form_example_4/") f_b_4 = html.br() f_a_5 = html.a('Example 5: automatic AJAX endpoint', attrs__href="form_example_5/") f_b_5 = html.br() f_a_k = html.a('Kitchen sink', attrs__href="form_kitchen/") table_header = Header('Table examples') # ...or just throw a big chunk of html in here table_links = mark_safe(""" <a href="table_readme_example_1/">Example 1 from the README</a><br> <a href="table_readme_example_2/">Example 2 from the README</a><br> <a href="table_auto_example_1/">Example 1 of auto table</a><br> <a href="table_auto_example_2/">Example 2 of auto table</a><br> <a href="table_kitchen_sink/">Kitchen sink</a><br> <a href="table_as_view/">Table.as_view() example</a><br> """) page_header = Header('Page examples') page_links = mark_safe(""" <a href="page_busy/">A busy page with lots of stuff</a><br> <a href="all_field_sorts">Show different type of form field types</a><br> <a href="all_column_sorts">Show different type of table column types</a> """) menu_header = Header('Menu examples') menu_examples = mark_safe(""" <a href="menu_test/">A menu example</a><br> """) # You can also nest pages admin = AdminPage() select_style = StyleSelector()
def rows(admin, **_): for app_name, models in items(django_apps.all_models): has_yielded_header = False for model_name, model in sorted(items(models), key=lambda x: x[1]._meta.verbose_name_plural): if not admin.apps.get(f'{app_name}_{model_name}', {}).get('include', False): continue if not has_yielded_header: yield Struct( name=app_verbose_name_by_label[app_name], verbose_app_name=app_verbose_name_by_label[app_name], url=None, format=lambda row, table, **_: Header(row.name, _name='invalid_name').bind(parent=table).__html__() ) has_yielded_header = True yield Struct( verbose_app_name=app_verbose_name_by_label[app_name], app_name=app_name, name=model._meta.verbose_name_plural.capitalize(), url='%s/%s/' % (app_name, model_name), format=lambda row, **_: row.name, )
def test_auto_h_tag(): # Start at h1 assert Header().bind(request=None).tag == 'h1' # Nesting doesn't increase level assert Fragment( children__child=Fragment( children__child=Header(), ) ).bind(request=None).__html__() == '<h1></h1>' # A header on a level increases the level for the next header assert Fragment( children__child=Fragment( children__child=Header( children__child=Header( children__child='h2', ) ) ) ).bind(request=None).__html__() == '<h1><h2>h2</h2></h1>' # Sibling headers get the same level assert Fragment( children__child=Fragment( children__child=Header( children__child=Header( children__child='h2'), children__another=Header( children__child='another h2', ) ) ) ).bind(request=None).__html__() == '<h1><h2>h2</h2><h2>another h2</h2></h1>'
def form_example_nested_forms(request): """Here we have two fields first_day, last_day and want to abstract out the validation behaviour. Maybe because we have several different forms that that edit different models that all have a first_day and a last_day field.""" class DateRangeField(Form): first_day = Field.date() last_day = Field.date() class Meta: @staticmethod def post_validation(form, **_): print("post validation", form.is_valid()) if form.is_valid(): if form.fields.first_day.value > form.fields.last_day.value: form.add_error("First day must be <= last day") class MyForm(Form): event = Field() # attr='' => instance.first_day, instance.last_day instead of instance.when.first_day, instance.when.last_day when = DateRangeField(attr='') class Meta: @staticmethod def actions__submit__post_handler(form, **_): if not form.is_valid(): return return html.pre(f"You posted {form.apply(Struct())}").bind( request=request) today = datetime.date.today() return Page( parts__title1=Header("Without instance"), parts__form1=MyForm(), parts__title2=Header("With instance"), parts__form2=MyForm( instance=Struct(first_day=today, last_day=today, event="Party")), )
class AdminPage(Page): admin_header = Header('Admin example') admin_a = html.p(html.a( 'Admin', attrs__href="iommi-admin/", ), ) log_in = html.a( 'Log in', attrs__href='/iommi-admin/login/?next=/', include=lambda request, **_: not request.user.is_authenticated, ) log_out = html.a( 'Log out', attrs__href='/iommi-admin/logout/', include=lambda request, **_: request.user.is_authenticated, )
class IssuePage(Page): title = Header( issue.name, children__number=html.span( format_html( f' <a href="{issue.get_absolute_url()}">#{issue.pk}</a>'), after=-1, attrs__class__faded=True, ), ) user_properties = html.ul( attrs__class__properties=True, children={ x.name: html.li( f'{x.name}: {x.data}', attrs__class=dict( unread=unread_data.is_unread(x.last_changed_time), unread2=unread_data.is_unread2(x.last_changed_time), ), ) for x in issue.user_properties.all() }) text_properties = html.ul( attrs__class__properties=True, children={ x.name: html.li( f'{x.name}: {x.data}', attrs__class=dict( unread=unread_data.is_unread(x.last_changed_time), unread2=unread_data.is_unread2(x.last_changed_time), ), ) for x in issue.text_properties.all() }) comments = RoomPage(room=issue.comments, unread_data=unread_data, parts__header__template='forum/blank.html' ) if issue.comments_id else None
def all_column_sorts(request): selected_shortcuts = ShortcutSelectorForm().bind( request=request).fields.shortcut.value or [] type_specifics = Namespace( choice__choices=['Foo', 'Bar', 'Baz'], multi_choice__choices=['Foo', 'Bar', 'Baz'], ) return Page(parts=dict(header=Header('All sorts of columns'), form=ShortcutSelectorForm(), table=Table( columns={ f'column_of_type_{t}': dict( type_specifics.get(t, {}), call_target__attribute=t, ) for t in selected_shortcuts }, rows=[DummyRow(i) for i in range(10)], )))
def all_field_sorts(request): some_choices = ['Foo', 'Bar', 'Baz'] return Page(parts=dict( header=Header('All sorts of fields'), form=Form( fields={ f'{t}__call_target__attribute': t for t in keys(get_members( cls=Field, member_class=Shortcut, is_member=is_shortcut )) if t not in [ # These only work if we have an instance 'foreign_key', 'many_to_many'] }, fields__radio__choices=some_choices, fields__choice__choices=some_choices, fields__choice_queryset__choices=TFoo.objects.all(), fields__multi_choice__choices=some_choices, fields__multi_choice_queryset__choices=TBar.objects.all(), fields__info__value="This is some information", fields__text__initial='Text', fields__textarea__initial='text area\nsecond row', fields__integer__initial=3, fields__float__initial=3.14, fields__password__initial='abc123', fields__boolean__initial=True, fields__datetime__initial=datetime.now(), fields__date__initial=date.today(), fields__time__initial=datetime.now().time(), fields__decimal__initial=3.14, fields__url__initial='http://iommi.rocks', fields__email__initial='*****@*****.**', fields__phone_number__initial='+1 555 555', actions__submit__include=False, ) ))
def test_get_title_of_header(): assert get_title(Header(children__foo='foo', children__bar='qwe').bind(request=req('get'))) == 'foo'