def test_page_constructor(): class MyPage(Page): h1 = html.h1() my_page = MyPage(parts__foo=html.div(_name='foo'), parts__bar=html.div()) assert ['h1', 'foo', 'bar'] == list(declared_members(my_page).parts.keys()) my_page = my_page.bind(request=None) assert ['h1', 'foo', 'bar'] == list(my_page.parts.keys())
def test_dispatch_return_part(): p = Part( endpoints__foo__func=lambda request, **_: html.div('foo', attrs__class__bar=True).bind(request=request), endpoints__bar__func=lambda request, **_: html.div('bar', attrs__class__baz=True), ) r = p.bind(request=req('get', **{'/foo': '7'})).render_to_response() assert b'<div class="bar">foo</div>' in r.content r = p.bind(request=req('get', **{'/bar': '7'})).render_to_response() assert b'<div class="baz">bar</div>' in r.content
class MyForm(Form): name = Field() color = Field.choice(choices=['Red', 'Green', 'Blue']) in_a_box = html.div( children__f1=Field.integer(attrs__class__column=True), children__plus=html.span("+", attrs__class={ 'column': True, 'is-narrow': True }), children__f2=Field.integer(attrs__class__column=True, ), children__equals=html.span("=", attrs__class={ 'column': True, 'is-narrow': True }), children__f3=Field.integer(attrs__class_column=True), iommi_style="bulma_query_form", attrs__class={ 'box': True, 'columns': True, 'is-vcentered': True }) class Meta: iommi_style = "bulma" title = "Children that are not fields" post_validation = post_valid actions__submit__post_handler = on_submit
def form_example_children_that_are_not_fields(request): def on_submit(form, **_): if not form.is_valid(): return return html.pre(f"You posted: {form.apply(Struct())}").bind(request=request) def post_validation(form, **_): if form.is_valid(): if form.fields.f1.value + form.fields.f2.value != form.fields.f3.value: form.add_error("Calculate again!") return Form( iommi_style="bulma", title="Children that are not fields", fields__name=Field(), fields__color=Field.choice(choices=['Red', 'Green', 'Blue']), fields__in_box=html.div( children__f1=Field.integer(attrs__class__column=True), children__plus=html.span("+", attrs__class={'column': True, 'is-narrow': True}), children__f2=Field.integer(attrs__class__column=True,), children__equals=html.span("=", attrs__class={'column': True, 'is-narrow': True}), children__f3=Field.integer(attrs__class_column=True), iommi_style="bulma_query_form", attrs__class={'box': True, 'columns': True, 'is-vcentered': True} ), post_validation=post_validation, actions__submit__post_handler=on_submit )
class ExamplesPage(Page): menu = menu footer = html.div( html.hr(), html.a('iommi rocks!', attrs__href='http://iommi.rocks/'), StyleSelector(), after=LAST, )
class LoginPage(Page): styling = html.style(""" .extra_links, .form { margin-left: auto; margin-right: auto; width: 710px; } """) form = LoginForm() links = html.div( attrs__class__extra_links=True, attrs__style={'text-align': 'right'}, children__create_account=html.a('Create account', attrs__href='/create-account/'), children__p=html.div(), children__forgot_passsword=html.a('Forgot your password?', attrs__href='/forgot-password/'), ) set_focus = html.script( mark_safe('document.getElementById("id_username").focus();'))
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_render_not_included_fragment(): assert html.div('foo', include=False).bind(request=None) is None
def live_edit_view(request, view, args, kwargs): view = get_wrapped_view(view) # Read the old code try: # view is a function based view filename = view.__globals__['__file__'] except AttributeError: # view is an iommi class from iommi.debug import filename_and_line_num_from_part filename, _ = filename_and_line_num_from_part(view) with open(filename) as f: entire_file = f.read() ast_of_entire_file = parso.parse(entire_file) is_unix_line_endings = '\r\n' not in entire_file ast_of_old_code = find_view(view, ast_of_entire_file) assert ast_of_old_code is not None flow_direction = request.GET.get('_iommi_live_edit') or 'column' assert flow_direction in ('column', 'row') if request.method == 'POST': try: code = request.POST['data'].replace('\t', ' ') if is_unix_line_endings: code = code.replace('\r\n', '\n') final_result = dangerous_execute_code(code, request, view, args, kwargs) if orig_reload is not None: # A little monkey patch dance to avoid one reload of the runserver when it's just us writing the code to disk # This only works in django 2.2+ def restore_auto_reload(filename): from django.utils import autoreload print('Skipped reload') autoreload.trigger_reload = orig_reload autoreload.trigger_reload = restore_auto_reload if isinstance(view, Part): ast_of_new_code = find_node(name=view.__class__.__name__, node=parso.parse(code), node_type='classdef') else: ast_of_new_code = find_node(name=view.__name__, node=parso.parse(code), node_type='funcdef') ast_of_old_code.children[:] = ast_of_new_code.children new_code = ast_of_entire_file.get_code() with open(filename, 'w') as f: f.write(new_code) return final_result except Exception as e: import traceback traceback.print_exc() error = str(e) if not error: error = str(e.__class__) return HttpResponse(json.dumps(dict(error=error))) return LiveEditPage( title='iommi live edit', h_tag__include=False, assets__code_editor=Asset.js( attrs=dict( src='https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js', integrity= 'sha512-GZ1RIgZaSc8rnco/8CXfRdCpDxRCphenIiZ2ztLy3XQfCbQUSCuk8IudvNHxkRA3oUg6q0qejgN/qqyG1duv5Q==', crossorigin='anonymous', ), after=-1, ), assets__live_edit_page_custom=Asset( tag='style', text=''' .container { padding: 0 !important; margin: 0 !important; max-width: 100%; } html, body { height: 100%; margin: 0; } .container { display: flex; flex-flow: <<flow_direction>>; height: 100%; } .container iframe { flex: 1 1 auto; } .container #editor { flex: 2 1 auto; } '''.replace('<<flow_direction>>', flow_direction), ), parts__result=html.iframe(attrs__id='result'), parts__editor=html.div( ast_of_old_code.get_code(), attrs__id='editor', ), parts__script=html.script( mark_safe(''' function iommi_debounce(func, wait) { let timeout; return (...args) => { const fn = () => func.apply(this, args); clearTimeout(timeout); timeout = setTimeout(() => fn(), wait); }; } var editor = ace.edit("editor"); editor.setTheme("ace/theme/cobalt"); editor.session.setMode("ace/mode/python"); editor.setShowPrintMargin(false); async function update() { let form_data = new FormData(); form_data.append('data', editor.getValue()); let response = await fetch('', { method: 'POST', body: form_data }); let foo = await response.json(); if (foo.page) { // TODO: get scroll position and restore it document.getElementById('result').srcdoc = foo.page; } } function foo() { iommi_debounce(update, 200)(); } editor.session.on('change', foo); editor.setFontSize(14); editor.session.setUseWrapMode(true); foo(); ''')), )
class MyPage(Page): part1 = Template('Template: {{foo}}\n') part2 = html.div(template=Template('Template2: {{foo}}')) class Meta: context__foo = 'foo'
class MyPage(Page): header = html.h1('Foo') body = html.div('bar bar')
class MyPage(Page): foo = html.div( 'foo', assets__my_asset=html.span(attrs__href='http://foo.bar/baz'))
class MyPage(Page): foo = html.div('foo', assets__my_asset=an_asset) bar = html.div('bar', assets__my_asset=an_asset)
def thanks(request, short): return html.div(html.h1('Thank you for submitting an URL'), html.p('Processing...'), html.a('Submit another', attrs__href='/submit/'))