Skip to content

Latest commit

 

History

History
221 lines (160 loc) · 6.88 KB

restish.rst

File metadata and controls

221 lines (160 loc) · 6.88 KB

Using Formish within Restish

Using a simple form withing Restish

We'll start off with one of the examples from the Formish documentation.

class SimpleSchema(schemaish.Structure):
    """ A simple sommets form """
    email = schemaish.String(validator=validatish.All(validatish.Required(), validatish.Email()))
    first_names = schemaish.String(validator=validatish.Required())
    last_name = schemaish.String(validator=validatish.Required())
    comments = schemaish.String()


def get_form():
    """ Creates a form and assigns a widget """
    form = formish.Form(SimpleSchema())
    form['comments'].widget = formish.TextArea()
    return form  


class Root(resource.Resource):
    """ Our form resource """

    @resource.GET()
    @templating.page('test.html')
    def html(self, request, form=None):
        """
        If the form is None then we get a clean form, otherwise show the
        form that was passsed back from an unsuccessful POST
        """
        if form is None:
            form = get_form()
        return {'form': form}

    @resource.POST()
    def POST(self, request):
        """
        Get a clean form and validate it against the request data that was
        submitted. Errors pass the form (with attached errors) back up to
        the page renderer. Success shows a thanks page (typically you would
        redirect here.
        """
        form = get_form()
        try:
            data = form.validate(request)
        except formish.FormError, e:
            return self.html(request, form)
        return self.thanks(request,data)

    def thanks(self, request, data):
        return http.see_other('/thanks')

We need to have the following in the test.html file

<div id="formbox">
  ${form()|n}
</div>

The steps when this form is created are as follows

  1. Get a copy of the form and put it on the page
  2. When POST'd, validate the returned request data. If this raises an exception, errors will have been bound to the form instance.
  3. (On Error): Pass the form with bound errors back up the page renderer.
  4. (On Success): Show a thanks page.

We can also pass the success and failure callables to the validate function to simplify the form handling.

class Resource(resource.Resource):

    @resource.GET()
    @templating.page('page.html')
    def html(self, request, form=None):
        if form is None:
            form = get_form()
        return {'form': form}

    @resource.POST()
    def POST(self, request):
        return get_contact_form().validate(request, self.html, self.thanks)

    def thanks(self, request, data):
        return http.see_other('/thanks')

Multiple Actions on a Form

If we have more than one action on a form

class Root(resource.Resource):

    def get_form(self):
        form = formish.Form( ('email', schemaish.String()) )
        form.addAction(self.check_email_domain, 'check')
        form.addAction(self.send_test_email, 'test')
        return form

    def check_email_domain(self, request, data):
        """ Check the domain has an MX or A record """

    def send_test_email(self, request, data):
        """ Send a test email to this address """

    @resource.GET()
    @templating.page('test.html')
    def html(self, request, form=None):
        if form is None:
            form = self.get_form()
        return {'form': form}

    @resource.POST()
    def POST(self, request):
        form = self.get_form()
        return form.validate(request, self.html, form.action)

Here we have pass the form.action method as the success callable. The whatever is in form.action (for example, check_email_domain) is called with (request, data).

Multiple Forms on a Page

If we have more than one form on a page, we can use the utility function, form_in_request to find out which one was posted.

class Root(resource.Resource):

    ##
    # Forms

    def _email_form(self):
        return formish.Form( ('email', schemaish.String()), name='email' )

    def _domain_form(self):
        return formish.Form( ('domain', schemaish.String()), name='domain' )

    ##
    # Form Handling

    def _POST_email(self, request):
        form = self._email_form()
        return form.validate(request, self.html, self.thanks)

    def _POST_domain(self, request):
        form = self._domain_form()
        return form.validate(request, self.html, self.thanks)

    ##
    # GET, POST, templating and thanks

    @resource.GET()
    def GET(self, request):
        return self.html(request)

    @resource.POST()
    def POST(self, request):
        handlers = {'email': self._POST_email, 'domain': self._POST_domain}
        return handlers[formish.form_in_request(request)](request)

    @templating.page('forms.html')
    def html(self, request, form=None):
        form_name = formish.form_in_request(request)
        form = {form_name: form}
        if form_name is not 'email':
            form['email'] = self._email_form()
        if form_name is not 'domain':
            form['domain'] = self._domain_form()
        return {'forms': forms}

    def thanks(self, request, data):
        return http.see_other('/thanks')

We could simplify this further, although I'm not sure this is quite as readable..

class Root(resource.Resource):

    def form(self,name):
        if name is 'email': 
            return formish.Form( ('email', schemaish.String()), name='email' )
        if name is 'domain':
            return formish.Form( ('domain', schemaish.String()), name='domain' )

    @resource.GET()
    def GET(self, request):
        return self.html(request)

    @resource.POST()
    def POST(self, request):
        form_name = formish.form_in_request(request)
        return self.form(name).validate(request, self.html, self.thanks)

    @templating.page('forms.html')
    def html(self, request, form=None):
        form_name = formish.form_in_request(request)
        form = {form_name: form}
        # Check each form, if it isn't the one passed in then fetch it.
        for f in ['email','domain']:
            if form_name is not f:
                form[f] = self.form(f)
        return {'forms': forms}

    def thanks(self, request, data):
        return http.see_other('/thanks')