class IndexPage(ExamplesPage): header = html.h1('Welcome to iommi examples application') logo = html.img( attrs__src= 'https://docs.iommi.rocks/en/latest/_static/logo_with_outline.svg', attrs__style__width='30%', )
class SubmitPage(Page): heading = html.h1('TriOptima URL Blessalizer') form = SubmitForm() set_focus = html.script( mark_safe('document.getElementById("id_url").focus();', )) admin = html.p(html.a('Admin', attrs__href='/entries'), ' (requires login)')
class CategoryPage(Page): title = html.h1(category.name) movies = Table( auto__rows=Movie.objects.filter(categories=category), columns__created__include=False, columns__modified__include=False, )
class DirectorPage(Page): title = html.h1(director.name) movies = Table( auto__rows=Movie.objects.filter(directors=director), columns__created__include=False, columns__modified__include=False, )
def test_fragment__render__simple_cases(): assert format_html('{}', html.h1('foo').bind(parent=None)) == '<h1>foo</h1>' assert format_html('{}', Fragment(children__child='foo<foo>').bind( parent=None)) == 'foo<foo>' assert fragment__render(Fragment(include=False), {}) == ''
class AlbumPage(Page): title = html.h1(album) text = html.a(album.artist, attrs__href=album.artist.get_absolute_url()) tracks = TrackTable( auto__rows=Track.objects.filter(album=album), columns__album__include=False, )
class IndexPage(ExamplesPage): header = html.h1('Form examples') description = html.p('Some examples of iommi Forms') examples = example_links(examples) all_fields = Action( display_name='Example with all types of fields', attrs__href='all_fields', )
class IndexPage(Page): title = html.h1("TMDB") welcome_text = "Welcome to my TMDB!" actors = Table( auto__model=Actor, page_size=5, columns__name=Column( cell__value=lambda row, **_: f"{row.last_name} {row.first_name}", ), columns__created__include=False, columns__modified__include=False, columns__first_name__include=False, columns__last_name__include=False, columns__countries__cell__format=lambda row, **_: mark_safe("".join( format_html( f'<a href="{country.get_absolute_url()}">{country}</a><br>') for country in row.countries.all())), ) movies = Table( auto__model=Movie, page_size=5, columns__created__include=False, columns__modified__include=False, columns__actors__cell__format=lambda row, **_: mark_safe("".join( format_html(f'<a href="{actor.get_absolute_url()}">{actor}</a><br>' ) for actor in row.actors.all())), columns__directors__cell__format=lambda row, **_: mark_safe("".join( format_html( f'<a href="{director.get_absolute_url()}">{director}</a><br>') for director in row.directors.all())), columns__countries__cell__format=lambda row, **_: mark_safe("".join( format_html( f'<a href="{country.get_absolute_url()}">{country}</a><br>') for country in row.countries.all())), columns__categories__cell__format=lambda row, **_: mark_safe("".join( format_html( f'<a href="{category.get_absolute_url()}">{category}</a><br>') for category in row.categories.all())), ) directors = Table( auto__model=Director, page_size=5, columns__name=Column( cell__value=lambda row, **_: f"{row.last_name} {row.first_name}", ), columns__created__include=False, columns__modified__include=False, columns__first_name__include=False, columns__last_name__include=False, columns__countries__cell__format=lambda row, **_: mark_safe("".join( format_html( f'<a href="{country.get_absolute_url()}">{country}</a><br>') for country in row.countries.all())), )
class MoviePage(Page): title = html.h1(movie.name) actors = Table( auto__rows=Actor.objects.filter(movies=movie), columns__created__include=False, columns__modified__include=False, ) directors = Table( auto__rows=Director.objects.filter(movies=movie), columns__created__include=False, columns__modified__include=False, )
class IndexPage(ExamplesPage): header = html.h1('Form examples') description = html.p('Some examples of iommi Forms') all_fields = html.p( Action( display_name='Example with all types of fields', attrs__href='all_fields', ), html.br(), after='example_11', ) class Meta: parts = example_links(examples)
class IndexPage(Page): header = html.h1('iommi examples') form_header = html.h2('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 = html.h2('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 = html.h2('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_examples = mark_safe(""" <h2>Menu examples</h2> <a href="menu_test/">A menu example</a><br> """) # You can also nest pages admin = AdminPage() select_style = StyleSelector()
class IndexPage(ExamplesPage): header = html.h1('Table examples') description = html.p('Some examples of iommi tables') all_fields = html.p( Action( display_name='Example with all available types of columns', attrs__href='all_columns', ), html.br(), after='example_6', ) class Meta: parts = example_links(examples)
class CountryPage(Page): title = html.h1(country.name) movies = Table( auto__rows=Movie.objects.filter(countries=country), columns__created__include=False, columns__modified__include=False, ) actors = Table( auto__rows=Actor.objects.filter(countries=country), columns__created__include=False, columns__modified__include=False, ) directors = Table( auto__rows=Director.objects.filter(countries=country), columns__created__include=False, columns__modified__include=False, )
class IndexPage(Page): header = html.h1('iommi examples') form_header = html.h2('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 = html.h2('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_kitchen_sink/">Kitchen sink</a><br> """) page_header = html.h2('Page examples') page_links = mark_safe(""" <a href="page_busy/">A busy page with lots of stuff</a><br> """) # You can also nest pages admin = AdminPage()
class IndexPage(Page): menu = SupernautMenu() title = html.h1(_('Supernaut')) welcome_text = html.div( _('This is a discography of the best acts in music!')) albums = AlbumTable( auto__model=Album, tag='div', header__template=None, cell__tag=None, row__template=Template(""" <div class="card" style="width: 15rem; display: inline-block;" {{ cells.attrs }}> <img class="card-img-top" src="/static/album_art/{{ row.artist }}/{{ row.name|urlencode }}.jpg"> <div class="card-body text-center"> <h5>{{ cells.name }}</h5> <p class="card-text"> {{ cells.artist }} </p> </div> </div> """), )
class IndexPage(Page): menu = SupernautMenu() title = html.h1(_('Supernaut')) welcome_text = html.div( _('This is a discography of the best acts in music!')) log_in = html.a( _('Log in'), attrs__href='/log_in/', include=lambda request, **_: not request.user.is_authenticated, ) log_out = html.a( _('Log out'), attrs__href='/log_out/', include=lambda request, **_: request.user.is_authenticated, ) albums = AlbumTable( auto__model=Album, tag='div', header__template=None, cell__tag=None, row__template=Template(""" <div class="card" style="width: 15rem; display: inline-block;" {{ cells.attrs }}> <img class="card-img-top" src="/static/album_art/{{ row.artist }}/{{ row.name|urlencode }}.jpg"> <div class="card-body text-center"> <h5>{{ cells.name }}</h5> <p class="card-text"> {{ cells.artist }} </p> </div> </div> """), )
def test_html_builder(): assert html.h1('foo').bind(request=None).__html__() == '<h1>foo</h1>'
def test_fragment(): foo = html.h1('asd').bind(parent=None) assert foo.__html__() == '<h1>asd</h1>'
class ArtistPage(Page): title = html.h1(artist.name) albums = AlbumTable(auto__rows=Album.objects.filter(artist=artist)) tracks = TrackTable(auto__rows=Track.objects.filter( album__artist=artist))
class IndexPage(ExamplesPage): header = html.h1('Page examples') description = html.p('Some examples of iommi Page') class Meta: parts = example_links(examples)
dispatch, Namespace, setdefaults_path, EMPTY, LAST, ) from django.apps import apps from tri_struct import Struct model_by_app_and_name = {(app_name, model_name): model for app_name, models in apps.all_models.items() for model_name, model in models.items()} app_and_name_by_model = {v: k for k, v in model_by_app_and_name.items()} admin_h1 = html.h1(html.a('Admin', attrs__href='/iommi-admin/'), after=0) @dispatch( app=EMPTY, table=EMPTY, ) def all_models(app, table, **kwargs): column_cls = table.call_target.cls.get_meta().member_class def app_data(): for app_name, models in apps.all_models.items(): for name, cls in models.items(): if app.get(app_name, {}).get(name, {}).get('include', True): yield Struct(app_name=app_name, model_name=name, model=cls)
class Admin(Page): header = html.h1(children__link=html.a('Admin'))
class Admin(Page): class Meta: table_class = Table form_class = Form apps__sessions_session__include = False parts__list_auth_user__columns__password__include = False table_class: Type[Table] = Refinable() form_class: Type[Form] = Refinable() apps: Namespace = Refinable() # Global configuration on apps level @reinvokable @dispatch( apps=EMPTY, parts=EMPTY, ) def __init__(self, parts, **kwargs): def should_throw_away(k, v): if isinstance(v, Namespace) and 'call_target' in v: return False if k == 'all_models': return True prefix_blacklist = [ 'list_', 'delete_', 'create_', 'edit_', ] for prefix in prefix_blacklist: if k.startswith(prefix): return True return False parts = { # Arguments that are not for us needs to be thrown on the ground k: None if should_throw_away(k, v) else v for k, v in items(parts) } super(Admin, self).__init__(parts=parts, **kwargs) @staticmethod def has_permission(request, operation, model=None, instance=None): return request.user.is_staff header = html.h1(children__link=html.a(children__text='Admin'), after=0) def own_evaluate_parameters(self): return dict(admin=self, **super(Admin, self).own_evaluate_parameters()) @classmethod @class_shortcut( table=EMPTY, ) def all_models(cls, request, table, call_target=None, **kwargs): if not cls.has_permission(request, operation='all_models'): raise Http404() def preprocess_rows(admin, rows, **_): return [ row for row in rows if admin.apps.get(f'{row.app_name}_{row.model_name}', {}).get('include', True) ] table = setdefaults_path( Namespace(), table, title='All models', call_target__cls=cls.get_meta().table_class, sortable=False, rows=[ Struct(app_name=app_name, model_name=model_name, model=model) for (app_name, model_name), model in items(model_by_app_and_name) ], preprocess_rows=preprocess_rows, columns=dict( app_name__auto_rowspan=True, app_name__after=0, model_name__cell__url=lambda row, **_: '%s/%s/' % (row.app_name, row.model_name), ), ) return call_target( parts__all_models=table, **kwargs ) @classmethod @class_shortcut( table=EMPTY, ) def list(cls, request, app_name, model_name, table, call_target=None, **kwargs): model = django_apps.all_models[app_name][model_name] if not cls.has_permission(request, operation='list', model=model): raise Http404() table = setdefaults_path( Namespace(), table, call_target__cls=cls.get_meta().table_class, auto__model=model, columns=dict( select__include=True, edit=dict( call_target__attribute='edit', after=0, cell__url=lambda row, **_: '%s/edit/' % row.pk, ), delete=dict( call_target__attribute='delete', after=LAST, cell__url=lambda row, **_: '%s/delete/' % row.pk, ), ), actions=dict( create=dict( display_name=f'Create {model._meta.verbose_name}', attrs__href='create/', ), ), query_from_indexes=True, bulk__actions__delete__include=True, **{ 'columns__' + field.name + '__bulk__include': True for field in get_fields(model) if not getattr(field, 'unique', False) }, ) return call_target( parts__header__children__link__attrs__href='../..', **{f'parts__list_{app_name}_{model_name}': table}, **kwargs, ) @classmethod @class_shortcut( form=EMPTY, ) def crud(cls, request, operation, form, app_name, model_name, pk=None, call_target=None, **kwargs): model = django_apps.all_models[app_name][model_name] instance = model.objects.get(pk=pk) if pk is not None else None if not cls.has_permission(request, operation=operation, model=model, instance=instance): raise Http404() form = setdefaults_path( Namespace(), form, call_target__cls=cls.get_meta().form_class, auto__instance=instance, auto__model=model, call_target__attribute=operation, ) return call_target( **{f'parts__{operation}_{app_name}_{model_name}': form}, **kwargs, ) @classmethod @class_shortcut( call_target__attribute='crud', operation='create', parts__header__children__link__attrs__href='../../..', ) def create(cls, request, call_target, **kwargs): return call_target(request=request, **kwargs) @classmethod @class_shortcut( call_target__attribute='crud', operation='edit', parts__header__children__link__attrs__href='../../../..', ) def edit(cls, request, call_target, **kwargs): return call_target(request=request, **kwargs) @classmethod @class_shortcut( call_target__attribute='crud', operation='delete', parts__header__children__link__attrs__href='../../../..', ) def delete(cls, request, call_target, **kwargs): return call_target(request=request, **kwargs) @classmethod def urls(cls): return Struct( urlpatterns=[ url(r'^$', cls.all_models), url(r'^(?P<app_name>\w+)/(?P<model_name>\w+)/$', cls.list), url(r'^(?P<app_name>\w+)/(?P<model_name>\w+)/create/$', cls.create), url(r'^(?P<app_name>\w+)/(?P<model_name>\w+)/(?P<pk>\d+)/edit/$', cls.edit), url(r'^(?P<app_name>\w+)/(?P<model_name>\w+)/(?P<pk>\d+)/delete/$', cls.delete), ] )
class ErrorPage(Page): header = html.h1('Not approved yet...')
def test_fragment__render__simple_cases(): assert format_html('{}', html.h1('foo')) == '<h1 >foo</h1>' assert format_html('{}', Fragment('foo<foo>')) == 'foo<foo>'
def test_html_builder_multi_arg(): assert html.h1('foo', 'bar').bind(request=None).__html__() == '<h1>foobar</h1>' assert html.h1('foo', html.p('bar')).bind( request=None).__html__() == '<h1>foo<p>bar</p></h1>'
class MyPage(Page): title = html.h1('Supernaut')
class MyPage(Page): h1 = html.h1()
class MyPage(Page): header = html.h1('Foo') body = html.div('bar bar')
class HelloWorldPage(Page): h1 = html.h1('Hello world!') p = html.p('This is an iommi page!')