john
john

Reputation: 4158

Maintain user input data while returning validation error

I'm using pyramid as my framework to work on a project. Since I used to do a lot of .ASP, whenever a user has given invalid input, I could just assign text to a label( via "runat" attribute then just simply assigning the message on the backend) which will signal to the user that the information they entered is invalid without erasing all their entered data. Is there an equivalent way to do this in python? Ultimately What I'd like to be able to do is report to the user if their data is valid (I could just redirect them to the same page) but, I'd prefer to not have to refresh the screen and have the users fill out the form a second time( or n number of time because of mistakes ).

Upvotes: 1

Views: 94

Answers (1)

Sergey
Sergey

Reputation: 12417

At the conceptual level, in a "traditional" (non-AJAX) scenario you do re-render the form each time user clicks Submit, there's simply no way around that. Your ASP applications were probably doing the same behind the scenes. The trick is, in case of an error, to re-render the form with the data user has already entered.

Usually it looks like this (assuming you're not using any form libraries and writing your forms by hand)

@view_config(...., renderer='myform.mak')
def my_view(context, request):

    if request.method == 'GET':
        # display an empty form to the user
        return {
            'page_title': 'Please fill out this boring form',
            'errors': {},
            'data': {},
        }
    elif request.method == 'POST':
        # an imaginary method which validates the data submitted by the user
        # returns a dict {field_name: error_message}, or None if validation passes
        errors = validate_myform(request.POST)
        if errors is None:
            # save the data and redirect elsewhere 
            save_myform(request.POST)
            return HTTPFound('/')
        else:
            return {
                'page_title': 'Validation error!', 
                'errors': errors,
                'data': request.POST,
            }

and in the template you just take care to pre-populate the inputs with data if present:

<input type="text" name="first_name" value="${data.get('first_name, '')}" />

and to render validation messages if the view function passes them:

%if 'first_name' in errors:
    <span class="error">${errors['first_name']}</span>
%endif

Form libraries (deform etc.) take care of the plumbing, but the principle is the same - view function receives a POST request, validates data and re-renders the form with the same data and error messages, if any.

Upvotes: 1

Related Questions