Overview
In the previous section we defined a simple template for the home page, and some of the modules that have not yet been implemented, such as users or posts, use mock objects as temporary placeholders.
In this chapter we will see how to fill these blanks with Web forms.
Web Forms are the most basic building elements in Web applications, and we will use forms to enable users to post and apply login functionality.
To complete the content of this chapter, you will need the microblog app code that was completed in the previous section, and make sure that the code is installed and functioning correctly.
Configuration
FLASK-WTF is the Flask framework extension for the Wtforms project, and we'll use him to help us with our Web forms.
Most flask extensions need to define related configuration items, so let's start by creating a configuration file in the app root directory for use. Let's create this first (fileconfig.py):
csrf_enabled = Truesecret_key = ' you-will-never-guess '
Quite simply, this is the 2 configuration items that flask-wtf need to use. Csrf_enabled configuration enables cross-site request attack protection, and in most cases you need to turn on this feature to make your app more secure.
Secret_key settings are valid when CSRF is enabled, which generates an encrypted token to be used for form validation, and you want to make sure that the key is complex enough not to be simply inferred.
Now this configuration file is basically available. Project creation completed we can create the following file and edit it (fileapp/__init__.py):
From flask import Flask app = Flask (__name__) app.config.from_object (' config ') from the app import views
User Login Form
A form created with FLASK-WTF is like an object that needs to inherit subclasses from the form class. You can then define the attribute variables of some classes in this subclass as form fields.
We want to create a login form for user identification. However, we will use OPENID to process the login process, unlike the usual way to verify the user name and password. The benefit of using OpenID is that we do not have to take care of the authentication process of the username and password and give it to OpenId, which will return the data to our user after verification. This is also more secure for users who use our site.
Using the OpenID login requires only a single string, which is then sent to the OpenID server. In addition, we also need to add a "Remember Me" box in the form, this is for those who do not want to visit our site every time the identity of the person to be authenticated. When this option is selected, the first time you log in will use a cookie to remember their login information in their browser, and the next time you enter the site, you will not need to sign in.
Let's start our first form (fileapp/forms.py):
From FLASK.EXT.WTF import form, TextField, booleanfieldfrom flask.ext.wtf import Required class LoginForm (Form): OpenID = TextField (' OpenID ', validators = [Required ()]) Remember_me = Booleanfield (' Remember_me ', default = False)
Enjoy this class, how concise, how clear. So simple, but very rich in connotation. We introduced a Form class and then inherited the class, adding both the TextField and Booleanfield fields as required.
A form validation function, Required, is also introduced, which can be appended to the field, which is used to check the data that the user fills in when the user submits the form. This Required function is used to prevent users from submitting empty data. There are a lot of different forms validation functions in FLASK-WTF, and we'll use them later.
form template
Now our problem is that we need a template to display this login form. The good news is that the login form class We just created knows how to convert the fields to HTML, so we just need to focus on the page layout. Here is the template for our login form (fileapp/templates/login.html):
{% extends "base.html"%} {% block content%}Sign In
{% Endblock%}
Let me just give it a second. In this template, we use the template inheritance again. Inherits template content from base.html using the extends statement. We will continue to use this approach in the template created later, so that we can keep all of our page layouts consistent.
This login template is slightly different from the normal HTML form, which uses the template parameter {{...}} to instantiate the form field, and the form field is derived from the form class we just defined, using the name of the form in the template parameter. When we use view functions to refer to a form class and render it to a template, we pay particular attention to the variable name that passes the form class to the template.
We turned on the CSRF (cross-site forgery request) feature in the configuration, and the template parameter {{Form.hidden_tag ()}} is replaced with a hidden form field that prevents CSRF functionality. After the CSRF feature is turned on, the template parameter needs to be added to all of the template's forms.
The fields in our defined form objects can also be rendered by the template, simply by adding template parameters like {{form.field_name}} in the appropriate location of the template, and the related fields will appear at the defined location. There are also some fields that can pass parameters, such as the OpenID field, and we add a parameter to increase the width of the display to 80 characters.
Since we do not have a button to define a Submit function in the form, we can only do it in normal form fields here. But it's just a button that doesn't have anything to do with any data in the form, and it does not have to be defined in the form class.
Form view
Witness the moment of miracles the last step, we're going to write a view function that renders the login form object to the template.
This function is fairly simple and uninteresting, because we just need to pass the form object to the template. Here is the entire contents of our view function (fileapp/views.py):
From flask import render_template, Flash, redirectfrom app import appfrom forms Import LoginForm # index view function sup Pressed for brevity @app. Route ('/login ', methods = [' GET ', ' POST ']) def login (): form = LoginForm () return Render_ Template (' login.html ', title = ' Sign in ', form = form)
We introduce the login form class, then instantiate it to a variable, and then pass the variable to the template. This is what you must do to render the form fields.
The above code also introduces two new objects: Falsh and redirect, which are not to be used until later.
Another thing to do is to add a new method to the route decorator. Let Flask understand. This view function supports GET and POST requests. Otherwise, this view function will only respond to GET requests. We need to get the data submitted after the user fills out the form, which is passed from the POST request.
You can learn the above by testing the program in the browser. According to the route associated with the view function, you should enter Http://localhost:5000/login in the browser
Since we haven't written any code to receive the data, now you have no effect on the Submit button in the page.
Receive data from a form
It is also worth mentioning that the processing of the form submission data by FLASK-WTF makes it easier for us to do the next thing. Here is a new version of our login view function, with the addition of form data validation and processing (fileapp/views.py):
@app. Route ('/login ', methods = [' GET ', ' POST ']) def login (): form = LoginForm () if Form.validate_on_submit (): Flash (' Login requested for openid= ' ' + form.openid.data + ' ", remember_me= ' + str (form.remember_me.data)) Return redirect ('/index ') return render_template (' login.html ', title = ' Sign in ', form = form)
Validate_on_submit () This method does all the work of form processing. If you are calling this method when you provide data to a table one-way user (for example, a chestnut: The user modifies the submitted data before it), it returns FALSE. When this happens, you know. Don't understand? is the submitted data validation does not pass, you will continue to render the template.
When the form's Validate_on_submit () method is called when the request is submitted, it gets all the submitted data from the request and then validates the data using the binding validation function in the form field. Returns TRUE when all data is validated through. This means that you can use these form data with confidence.
It returns False as long as there is a field validation that does not pass. At this point we need to return the data to the user, so that they can correct the error data. Next we'll see how to display the error message to the user when the data validation fails.
When the Validate_on_submit () method returns True, our view function calls two new functions. They are all introduced from flask, and the flash function is used to display the defined message in the next open page. We use it for debugging now. Because we have not yet done the user login module, so we just need to put the data submitted by the user to display a bit on the line. Flash functions are useful, such as providing message feedback for some of the user's actions.
The Flash function provides a message that does not automatically appear on our site page, so we need to do something to make it appear on the page. To make this exciting feature available for all our pages, add it to the base template, and here's the updated base template (fileapp/templates/base.html):
{% if title%} {{title}}-Microblog {% Else%} Microblog {% ENDIF%} Microblog:home {% with messages = Get_flashed_messages ()%} {% If messages%}
{% to message in Mes Sages%}
{% endfor%}
{% ENDIF%} {% Endwith%}
The ability to display flash messages in a template I hope you understand.
Another new function that we use in the view function is redirect. This function notifies the user that the browser jumps to the specified address. In our view function, we use it to jump to the first page. Notice that the Flash function passes the message on the page after the jump ends.
It's an exciting time to run our program and see how the form works. Don't fill out the OpenID field in the form to see how Required this verification function works, blocking all requests for empty data from miles away.
Improve field validation
Our program is currently in good condition, the submission of non-compliant data will be blocked, but also return to the form for users to modify, basically meet our requirements.
But there seems to be something less. If we give the user a hint after the user submits the data, let them know what causes it, wouldn't it be wonderful! Luckily, it's easy to solve this problem with FLASK-WTF.
When form field validation fails, FLASK-WTF adds an error message to the form object. These messages are also available in templates, so we just need to add a little bit of stuff to the template to be OK.
This is the login template (fileapp/templates/login.html) where we added the authentication message:
{% extends "base.html"%} {% block content%}Sign In
{% Endblock%}
We only added a looping statement to the right of the OpenID field, which shows the message that the OpenID field failed to validate. No matter how many fields your form has, error messages for all form field validation failures can be used in the same way as form.errors. Field names. In this form, we are form.errors.openid. In order for the error message to be noticed by the user, we added a red CSS style to the message.
Handling OpenID Login
In real life, we find that many people do not know that they have some public accounts. Some big-names websites or service providers will provide their members with a public account certification. For a chestnut, if you have a Google account, you actually have a public account, similar to Yahoo, AOL, Flickr and so on.
To make it easier for our users to use their public accounts, we will add links to these public accounts to a list so that users do not have to enter them manually.
We are going to define some of the public account providers that are available to the user in a list, and the list is in the config file (fileconfig.py):
csrf_enabled = Truesecret_key = ' you-will-never-guess ' openid_providers = [ {' name ': ' Google ', ' url ': ' HTTPS://WWW.G Oogle.com/accounts/o8/id '}, {' name ': ' Yahoo ', ' url ': ' https://me.yahoo.com '}, {' name ': ' AOL ', ' url ': ' http:/ /openid.aol.com/
'}, {' name ': ' Flickr ', ' url ': ' http://www.flickr.com/
'}, {' Name ': ' Myopenid ', ' url ': ' https://www.myopenid.com '}]
The next step is to use this list in our login view function:
@app. Route ('/login ', methods = [' GET ', ' POST ']) def login (): form = LoginForm () if Form.validate_on_submit (): Flash (' Login requested for openid= ' ' + form.openid.data + ' ", remember_me= ' + str (form.remember_me.data)) Return redirect ('/index ') return render_template (' login.html ', title = ' Sign in ', form = form, providers = app.config[' Openid_providers '])
We introduced the configuration list of the public account provider from App. Config and then introduced it as a parameter to the template using the Render_template function.
Next thing to do I think you can guess, we need to show these providers in the login template.
{% extends "base.html"%} {% block content%}Sign In
{% Endblock%}
This time the template adds something that seems a bit more. Some public accounts need to provide user names, in order to solve this we used a bit of JavaScript. When the user clicks on the relevant public account link, the public account that requires the user name prompts the user for the user name, and JavaScript processes the user name into a usable public account, and then inserts it into the OpenID field's text box.
The following is shown on the login page after clicking on the Google Link:
Conclusion
We are currently making some progress in the user login form, but the user is not able to log on to the site or do anything. At the moment we have been doing a little on the login interface because we have not yet recorded everything in the database.
So from the next section, we're going to make a whole database, and then we can actually complete our login system. Don't go away, keep your eye on it.
Weibo (microblog) the current version of the source code from the following address download:
Download Address: Microblog-0.3.zip