def test_ajax_not_trigger_bind(): p = Page( parts=dict( form=Form( endpoints__foo__func=lambda value, **_: HttpResponse('bar'), ), exploding_form=ExplodingForm(), ) ) p = p.bind( request=req( 'get', **{ '/foo': '', }, ) ) assert p.render_to_response().content == b'bar' with pytest.raises(Exception) as e: # noinspection PyStatementEffect p.parts.exploding_form assert str(e.value) == 'Boom'
def test_perform_post_with_no_dispatch_parameter(): target = Page().bind(request=req('post')) with pytest.raises(AssertionError) as e: target.render_to_response() assert str(e.value) == 'This request was a POST, but there was no dispatch command present.'
def test_custom_endpoint_on_page(): p = Page(endpoints__test__func=lambda value, **_: 7).bind( request=req('get', **{'/test': ''})) assert p.endpoints.test.include is True assert p.endpoints.test.endpoint_path == '/test' assert p.render_to_response().content == b'7'
def test_post_not_trigger_bind(): p = Page( parts=dict( form=Form( fields__foo=Field(), ), exploding_form=ExplodingForm(), ) ) p = p.bind( request=req( 'post', **{ '-': '', 'foo': 'bar', }, ) ) assert p.parts.form.fields.foo.value == 'bar' with pytest.raises(Exception) as e: # noinspection PyStatementEffect p.parts.exploding_form assert str(e.value) == 'Boom'
def test_context_processor_is_called_on_render_root(): part = Page( context__root_part_context_variable='root_part_context_variable', ) t = render_root( part=part.bind(request=req('get')), template_name='test_context_processor_is_called_on_render_root.html', context=dict(my_context_variable='my_context_variable'), ) assert t == 'context_processor_is_called\nroot_part_context_variable\nmy_context_variable\n'
def page_live(request): return Page( parts__foo='Test', parts__circle=mark_safe( '<svg><circle cx=50 cy=50 r=40 stroke=green fill=yellow stroke-width=4></svg>' ), parts__bar=Table(auto__model=TFoo, page_size=2))
def test_deprecated_assets_style(settings, capsys): settings.DEBUG = True with register_style( 'my_style', Style( test, assets__an_asset=Asset.css(attrs__href='http://foo.bar/baz'), ), ): captured = capsys.readouterr() assert 'Warning: The preferred way to add top level assets config' in captured.out settings.DEBUG = False expected = prettify( ''' <!DOCTYPE html> <html> <head> <title/> <link href='http://foo.bar/baz' rel="stylesheet"/> </head> <body/> </html> ''' ) actual = prettify(Page(iommi_style='my_style').bind(request=req('get')).render_to_response().content) assert actual == expected
def test_context_processor_is_called_on_render_root(): style_name = 'test_context_processor_is_called_on_render_root' style = Style( base, base_template='test_context_processor_is_called_on_render_root.html', ) register_style(style_name, style) part = Page( context__root_part_context_variable='root_part_context_variable', iommi_style=style_name, ) t = render_root( part=part.bind(request=req('get')), context=dict(my_context_variable='my_context_variable'), ) assert t == 'context_processor_is_called\nroot_part_context_variable\nmy_context_variable\n'
def test_invalid_enpoint_path(settings): p = Page().bind(request=req('get', **{'/foo': ''})) assert p.render_to_response( ).content == b'{"error": "Invalid endpoint path"}' settings.DEBUG = True with pytest.raises(InvalidEndpointPathException) as e: p.render_to_response() assert str(e.value) == """ Given path /foo not found. Short alternatives: '' debug_tree Long alternatives: '' endpoints/debug_tree """.strip()
def table_two(request): return Page(parts__table_1=Table( auto__model=Foo, columns__a__filter__include=True, page_size=5, ), parts__table_2=Table( auto__model=TBar, columns__b__filter__include=True, page_size=5, query__advanced__include=False, ))
def index(request): if not Category.objects.filter(user=request.user).exists(): return Page(template='money/index_no_categories.html') transactions = Transaction.objects.filter(user=request.user) if not transactions.exists(): return Page(template='money/index_welcome.html') unclassified = transactions.filter(category=None) if not unclassified.exists(): return Page( parts__text=gettext('All transactions have been classified')) # <p ></p> # <div style="font-size: 80%; padding-top: 20px"> # {% trans "Latest transaction" %}: {{ last_transaction.date|relative_date }} # </div> try: last_transaction = Transaction.objects.filter( user=request.user, virtual=False).order_by('-date')[0] except (Transaction.DoesNotExist, IndexError): last_transaction = None return Page(parts__table=TransactionTable(rows=unclassified, ), context={ 'matched_count': Transaction.objects.filter(user=request.user, category__isnull=False).count(), 'unmatched_count': Transaction.objects.filter(user=request.user, category__isnull=True).count(), 'last_transaction': last_transaction, 'categories': Category.objects.filter(user=request.user), })
def entries(request): return Page(parts=dict( admin_table=EntryAdminTable(), approve_table=EntryApproveTable(), unapprove_table=EntryUnapproveTable(), helper_script=html.script( mark_safe(''' function copyToClipBoard(url) { const temp = document.createElement('textarea'); temp.value = url; document.body.appendChild(temp); temp.select(); document.execCommand('copy'); document.body.removeChild(temp); } ''')), ))
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 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")), )
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) table = setdefaults_path( table, sortable=False, rows=app_data(), columns=dict( app_name=column_cls(auto_rowspan=True), model_name=column_cls(cell__url=lambda row, **_: '%s/%s/' % (row.app_name, row.model_name)), )) return Page(parts__header=admin_h1, parts__title=html.h2('All models'), parts__table=table(), **kwargs)
def test_assets_render_from_style(): with register_style( 'my_style', Style( test, root__assets__an_asset=Asset.css(attrs__href='http://foo.bar/baz'), ), ): expected = prettify( ''' <!DOCTYPE html> <html> <head> <title/> <link href='http://foo.bar/baz' rel="stylesheet"/> </head> <body/> </html> ''' ) actual = prettify(Page(iommi_style='my_style').bind(request=req('get')).render_to_response().content) assert actual == expected
def test_h_tag_callable(): p = Page(title=lambda request, **_: request.GET['foo']).bind( request=req('get', foo='title here')) assert '<h1>Title here</h1>' in p.__html__()
def test_title_basic(): assert '<h1>Foo</h1>' == Page(title='foo').bind( request=req('get')).__html__()
def test_title_empty(): assert '' in Page().bind(request=req('get')).__html__()
def test_title_attr(): assert '<h1 class="foo">Foo</h1>' == Page( title='foo', h_tag__attrs__class__foo=True).bind(request=req('get')).__html__()
def test_as_view(): view = Page(parts__foo='##foo##').as_view() assert '##foo##' in view(req('get')).content.decode()
def table_two(request): return Page(parts__table_1=Table(auto__model=Foo, columns__a__filter__include=True), parts__table_2=Table(auto__model=TBar, columns__b__filter__include=True))