class MyPage(Page): header = Fragment() some_form = Form(fields=Namespace(fisk=Field(), )) some_other_form = Form(fields=Namespace( fjomp=Field(), fisk=Field(), )) a_table = Table( model=TFoo, columns=Namespace( columns=Column(), fusk=Column(attr='b', filter__include=True), ), )
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 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 KitchenForm(Form): kitchen_foo = Field() fisk = Field.multi_choice( choices=[1, 2, 3, 4], parse=choice_parse, initial=[1, 2], editable=False ) textarea = Field.textarea(initial='initial value') radio = Field.radio(choices=['foo!!_"', 'bar', 'baz']) checkbox = Field.boolean() date = Field.date() choice = Field.choice(choices=['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'X']) choice_with_groups = Field.choice( choices=['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'X'], choice_to_optgroup=lambda choice, **_: choice[0] if choice[0].islower() else None )
class FruitForm(Form): class Meta: @staticmethod def post_validation(form, **_): # Notice that post_validation is run, even if there are invalid fields, # so you either have to check that fields that you are interested in # are not None, or alternatively if you only want to run your validation if all fields # passed their individual checks you can just call form.is_valid (see below). # BUT when form.is_valid is called outside of a Form's post_validation # handler its result includes errors caused by the post_validation (as you # would expect). if form.is_valid( ) and form.fields.name.value == "tomato" and form.fields.color.value == "Blue": # Or alternatively call form.add_error raise ValidationError("Tomatoes are not blue") @staticmethod def actions__submit__post_handler(form, **_): if form.is_valid(): return html.pre(f"You posted: {form.apply(Struct())}" ).bind(request=request) name = Field() amount = Field.integer() color = Field.choice(choices=['Red', 'Green', 'Blue'], )
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
class ForgotPasswordForm(Form): username_or_email = Field( is_valid=lambda parsed_data, **_: (parsed_data is not None, 'Unknown username or email'), parse=parse) class Meta: title = 'Request password reset' actions__submit__display_name = 'Send reset email' def actions__submit__post_handler(form, **_): if not form.is_valid(): return user = form.fields.username_or_email.value code = token_hex(64) ResetCode.objects.filter(user=user).delete() ResetCode.objects.create(user=user, code=code) send_mail( subject=f'{settings.INSTALLATION_NAME} password reset', message=f"Your reset code is: \n{code}", from_email=settings.NO_REPLY_EMAIL, recipient_list=[user.email], ) return HttpResponseRedirect(reverse(reset_password))
def extra_fields(request): class FooTable(Table): name = Column(filter__include=True) table = FooTable(rows=Foo.objects.all(), query__form__fields__my_extra_field=Field( attr=None, initial="Hello World")).bind(request=request) print(table.query.form.fields.my_extra_field.value) return table
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)
class FruitForm(Form): class Meta: @staticmethod def actions__submit__post_handler(form, **_): if form.is_valid(): return html.pre(f"You posted: {form.apply(Struct())}" ).bind(request=request) name = Field() amount = Field.integer() color = Field.choice(choices=['Red', 'Green', 'Blue'], )
class SubmitForm(Form): short = Field(initial=random_short(), is_valid=lambda parsed_data, **_: (not Entry.objects.filter(short=parsed_data.strip()). exists(), 'Short name already in use')) url = Field( is_valid=lambda parsed_data, **_: (not Entry.objects.filter( url=parsed_data.strip()).exists(), 'URL already submitted')) class Meta: @staticmethod def actions__submit__post_handler(form, **_): if form.is_valid(): entry = Entry( short=form.fields.short.value, url=form.fields.url.value, created_at=timezone.now(), valid_to=timezone.now() + timedelta(days=30), ) entry.save() return HttpResponseRedirect(f'/thanks/{entry.short}')
class LoginForm(Form): username = Field() password = Field.password() next = Field.hidden(initial=request.GET.get('next', '/')) class Meta: title = 'Login' def actions__submit__post_handler(form, **_): if 'user' in form.extra: login(request, form.extra.user) return HttpResponseRedirect(form.fields['next'].value or '/') def is_valid(self): if not super(LoginForm, self).is_valid(): return False username = self.fields['username'].value password = self.fields['password'].value if username and password: try: user = User.objects.get(username=username) except User.DoesNotExist: return False self.extra.user = user if authenticate(request=request, username=username, password=password): return True try: username = User.objects.get(username=username) if b64encode(sha1(password.encode()).digest()).decode( ) == user.password: user.set_password(password) # upgrade password user.save() authenticate(request=request, username=username, password=password) except User.DoesNotExist: pass return False
class FruitForm(Form): class Meta: @staticmethod def post_validation(form, **_): # Notice that post_validation is run, even if there are invalid fields # hence the 'or' below if (form.fields.name.value or '').lower( ) == "tomato" and form.fields.color.value == "Blue": # Or alternatively call form.add_error raise ValidationError("Tomatoes are not blue") @staticmethod def actions__submit__post_handler(form, **_): if form.is_valid(): return html.pre(f"You posted: {form.apply(Struct())}" ).bind(request=request) name = Field() amount = Field.integer() color = Field.choice(choices=['Red', 'Green', 'Blue'], )
class LoginForm(Form): username = Field(display_name=gettext('Username')) password = Field.password(display_name=gettext('Password')) class Meta: title = gettext('Login') @staticmethod def actions__submit__post_handler(form, **_): if form.is_valid(): user = auth.authenticate( username=form.fields.username.value, password=form.fields.password.value, ) if user is not None: request = form.get_request() auth.login(request, user) return HttpResponseRedirect(request.GET.get('next', '/')) form.add_error(gettext('Unknown username or password'))
class ResetPasswordForm(Form): reset_code = Field( is_valid=lambda parsed_data, **_: (parsed_data is not None, 'Invalid reset password code'), parse=parse) new_password = Field.password() confirm_password = Field.password( is_valid=lambda parsed_data, **_: (parsed_data == request.POST.get( 'new_password'), 'Passwords do not match')) class Meta: title = 'Reset password' def actions__submit__post_handler(form, **_): if form.is_valid(): reset_code = form.fields.reset_code.value reset_code.user.set_password( form.fields.new_password.value) login(request, reset_code.user) reset_code.delete() return HttpResponseRedirect('/')
class MyForm(Form): my_field = Field(extra__foo=17, )
class FruitForm(Form): name = Field() amount = Field.integer() color = Field.choice(choices=['Red', 'Green', 'Blue'], )
class SinkForm(Form): foo = Field()