Reread Dog Book 3-Web form

Keywords: Python Flask

Web form

Cross Site Request Forgery protection

  • By default, flask WTF can protect all forms from Cross Site Request Forgery (CSRF) attacks. When a malicious website sends a request to another website that the attacker has logged in, it will trigger a CSRF attack. In order to implement CSRF protection, the flash WTF program needs to set a key. Flash WTF uses this key to generate an encryption token, and then uses the token to verify the authenticity of the form data in the request. For example:

    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'hard to guess string'
    # The app.config dictionary can be used to store configuration variables for frameworks, extensions, and programs themselves. It can be operated by using the standard dictionary syntax.
    # SECRET_ The key configuration variable is a general key that can be used in flash and multiple third-party extensions.
    

    In the production environment, the secret key should also be written in a secure location, such as the environment variable of the server.

Form class

  • When using flask WTF, each Web Form is represented by a class that inherits from Form. This class defines a set of fields in a Form, and each field is represented by an object. A field object can be attached to one or more validation functions. The validation function is used to verify whether the input value submitted by the user meets the requirements. For example:

    from flask_wtf import Form
    from wtforms import StringField, SubmitField
    from wtforms.validators import Required
    
    # The StringField class represents the < input > element whose attribute is type="text"
    # The SubmitField class represents the < input > element whose attribute is type="submit"
    class NameForm(Form):
        name = StringField('What is your name ?', validators=[Required()])
        submit = SubmitField('Submit')
    
  • HTML standard fields supported by WTForms

    Field typeeffect
    StringFieldText field
    TextAreaFieldMultiline text field
    PasswordFieldPassword text field
    HiddenFieldHide text fields
    DateFieldText field, the value is in datetime.date format
    DateTimeFieldText field, the value is in datetime.datetime format
    IntegerFieldText field with integer value
    RadioFieldA set of radio boxes
    SelectFieldDrop down list
    FileFieldFile upload field
    FormFieldForm submit button
  • WTForms validation function

    Verification functioneffect
    EmailVerify email address
    EqualToCompare the values of two fields, such as secondary password authentication
    IPAddressVerify IPv4 network address
    LengthVerify the length of the input string
    NumberRangeVerify that the value entered is within the numeric range
    RequiredMandatory Field
    RegexpValidate input values using regular expressions
    URLVerify that the input is a URL
    AnyOfEnsure that the input value is in the list of optional values
    NoneOfEnsure that the input value is not in the list of optional values

Render form as HTML

  • A simple form can be generated in the template by passing in the parameter form:

    <form method="POST">
        {{ form.hidden_tag() }} 
        {{ form.name.label }} {{ form.name() }}
        {{ form.name.label }} {{ form.name(id='my-text-field') }}
        {{ form.submit() }}
    </form>
    
  • To improve the appearance of the form, you can pass the parameters into the function that renders the field, and the passed parameters will be converted into the HTML attributes of the field. For example, you can specify an id or class attribute for a field, and then define CSS styles:

    <form method="POST">
        {{ form.hidden_tag() }} 
        {{ form.name.label }} {{ form.name(id='my-text-field') }}
        {{ form.submit() }}
    </form>
    
  • When processing a form in the view, the view function index() not only renders the form, but also receives the data in the form:

    @app.route('/', methods=['GET', 'POST'])  # Define request method
    def index():
        name = None
        form = NameForm()
        if form.validate_on_submit():  # Validate form parameters
            name = form.name.data
            form.name.data = ''  # Empty form data
        return render_template('index.html', form=form, name=name)
    

Redirect & user sessions

  • The view function implements redirection and user session:

    from flask import (
    	Flask, render_template, session, redirect, url_for
    )
    
    @app.route('/', methods=['GET', 'POST'])
    def index():
        form = NameForm()
        if form.validate_on_submit():
            session['name'] = form.name.data  # Store user information
            return redirect(url_for('index'))  # Redirect to home page
        return render_template('index.html', form=form, name=session.get('name'))
    

Flash flash

  • After the user submits a login form with an error, the response sent back by the server re renders the login form, and a message is displayed on the form to prompt the user that the user name or password is wrong. At this time, you can use Flash:

    from flask import Flask, render_template, session, redirect, url_for, flash
    @app.route('/', methods=['GET', 'POST'])
    def index():
        form = NameForm()
        if form.validate_on_submit():
            old_name = session.get('name')
            if old_name is not None and old_name != form.name.data:
                flash('Looks like you have changed your name!')
                session['name'] = form.name.data
                return redirect(url_for('index'))
            return render_template('index.html',
                                   form = form, name = session.get('name'))
    
  • Calling flash() function alone can not display the messages. The template used by the program should render these messages. It's best to render flash messages in the base template so that all pages can use them. Flash template use get_ flashed_ Get and render messages using the messages() function:

    <div class="container">
        {% for message in get_flashed_messages() %}
        <div class="alert alert-warning">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            {{ message }}
        </div>
        {% endfor %}
    </div>
    

    The reason for using the loop in the template is that in the previous request loop, a message will be generated every time the flash() function is called, so there may be multiple messages waiting in the queue for display. get_ flashed_ The messages obtained by the messages () function will not be returned again in the next call, so the Flash message is displayed only once and then disappears.

Posted by hach22 on Tue, 19 Oct 2021 00:17:18 -0700