Skip to content

Commit f8264b3

Browse files
committed
bunch of edits
1 parent 1881321 commit f8264b3

File tree

1 file changed

+30
-20
lines changed

1 file changed

+30
-20
lines changed

flask/part4_forms/README.md

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,20 @@ We will install the **Flask-WTF** extension to help us work with forms in Flask.
2727
In Terminal, change into your Flask projects folder and activate your virtualenv there. Then install at the bash prompt (`$`):
2828

2929
```bash
30-
pip install Flask-WTF
30+
pip3 install Flask-WTF
3131
```
3232

3333
We will also install the **Flask-Bootstrap** extension to provide Bootstrap styles for our forms.
3434

3535
```bash
36-
pip install flask-bootstrap
36+
pip3 install Flask-Bootstrap4
3737
```
3838

3939
This installation is done only once in any virtualenv. It is assumed you already have Flask installed here.
4040

41+
* [Flask-WTF docs](http://flask.pocoo.org/docs/1.0/patterns/wtforms/); more details in [WTForms docs](https://wtforms.readthedocs.io/en/stable/)
42+
* [Flask-Bootstrap docs](https://pythonhosted.org/Flask-Bootstrap/)
43+
4144
## Imports for forms with Flask-WTF and Flask-Bootstrap
4245

4346
You will have a long list of imports at the top of your Flask app file:
@@ -68,7 +71,7 @@ Bootstrap(app)
6871

6972
Flask allows us to set a "secret key" value. You can grab a string from a site such as [RandomKeygen](https://randomkeygen.com/). This value is used to prevent malicious hijacking of your form from an outside submission.
7073

71-
Flask-WTF's `FlaskForm` will automatically create a secure session with CSRF (cross-site request forgery) protection if this key-value is set. Don't publish the actual key on GitHub!
74+
Flask-WTF's `FlaskForm` will automatically create a secure session with CSRF (cross-site request forgery) protection if this key-value is set. **Don't publish the actual key on GitHub!**
7275

7376
You can read more about `app.config['SECRET_KEY']` in [this StackOverflow post](https://stackoverflow.com/questions/22463939/demystify-flask-app-secret-key).
7477

@@ -86,7 +89,9 @@ class NameForm(FlaskForm):
8689
submit = SubmitField('Submit')
8790
```
8891

89-
Note that `StringField` and `SubmitField` were **imported** at the top of the file. If we needed other form fields in this form, we would need to import those. See a [list of all WTForms field types](WTForms-field-types.csv).
92+
[Learn more about classes in Python here.](https://docs.python.org/3/tutorial/classes.html#a-first-look-at-classes)
93+
94+
Note that `StringField` and `SubmitField` were **imported** at the top of the file. If we needed other form fields in this form, we would need to import those also. See a [list of all WTForms field types](WTForms-field-types.csv).
9095

9196
Note that several field types (such as `RadioField` and `SelectField`) must have an option `choices=[]` specified, after the label text. Within the list, each choice is a pair in this format: `('string1', 'string2')`.
9297

@@ -100,12 +105,15 @@ Now we will use the form in a Flask route:
100105
@app.route('/', methods=['GET', 'POST'])
101106
def index():
102107
names = get_names(ACTORS)
103-
# you must tell the variable 'form' what you named the class, above
104-
# 'form' is the variable name used in this template: index.html
108+
# ACTORS is a list of dictionaries for 100 movie actors, imported with -
109+
# from data import ACTORS
105110
form = NameForm()
111+
# 'form' is the variable name used in this template: index.html
112+
# NameForm() is the class, explained above
106113
message = ""
107114
if form.validate_on_submit():
108115
name = form.name.data
116+
# get the text (data) out of the form control with the name "name"
109117
if name in names:
110118
# empty the form field
111119
form.name.data = ""
@@ -117,7 +125,7 @@ def index():
117125
return render_template('index.html', names=names, form=form, message=message)
118126
```
119127

120-
The crucial line is where we assign our configured form object to a new variable:
128+
A crucial line is where we assign our configured form object to a new variable:
121129

122130
```python
123131
form = NameForm()
@@ -156,13 +164,13 @@ Before we break all that down and explain it, let's look at the code in the temp
156164

157165
<img src="../images/rabbit_hat.png" alt="Drawing of magician pulling rabbit from hat">
158166

159-
Note that in the Flask route, we passed the variable `form` to the template *index.html*:
167+
Note that in the Flask route function, we passed the variable `form` to the template *index.html*:
160168

161169
```python
162170
return render_template('index.html', names=names, form=form, message=message)
163171
```
164172

165-
So when you use `wtf.quick_form()`, the argument in the parentheses must be the *variable* that represents the form you created in the app.
173+
So when you use `wtf.quick_form()`, the argument inside the parentheses must be the *variable* that represents the form you created in the app.
166174

167175
```python
168176
form = NameForm()
@@ -175,7 +183,7 @@ We discussed the configuration of `NameForm` above.
175183
Before reading further, try out [a working version of this app](https://weimergeeks.com/flask_form/). The complete code for the app is in this repo in the folder *actors_app*.
176184

177185
1. You type an actor's name into the form and submit it.
178-
2. If the actor's name is in the data source, the app loads a detail page for that actor.
186+
2. If the actor's name is in the data source (ACTORS), the app loads a detail page for that actor. (Photos of bears stand in for real photos of the actors.)
179187
3. Otherwise, you stay on the same page, the form is cleared, and a message tells you that actor is not in the database.
180188

181189
```python
@@ -205,7 +213,7 @@ First we have the route, as usual, but with a new addition for handling form dat
205213
@app.route('/', methods=['GET', 'POST'])
206214
```
207215

208-
Every HTML form has two possible methods, `GET` and `POST`. `GET` simply requests a response from the server. `POST`, however, sends a request with data attached in the body of the request; this is the way most forms are submitted.
216+
Every HTML form has two possible methods, `GET` and `POST`. `GET` simply requests a response from the server. `POST`, however, sends a request **with data attached** in the body of the request; this is the way most forms are submitted.
209217

210218
This route needs to use both methods because when we simply open the page, no form was submitted, and we're opening it with `GET`. When we submit the form, this same page is opened with `POST` if the actor's name (the form data) was not found.
211219

@@ -259,8 +267,12 @@ This if-statement is specific to this app. It checks whether the `name` (that wa
259267
return redirect( url_for('actor', id=id) )
260268
```
261269

270+
Thus `redirect( url_for('actor', id=id) )` is calling a different route here in the same Flask app script. [See lines 46-55 here.](actors_app/actors.py)
271+
262272
As far as **using forms with Flask** is concerned, you don't need to worry about the actors and their ids, etc. What is important is that the route function can be used to *evaluate the data sent from the form.* We check to see whether it matched any of the actors in a list, and *a different response* will be sent based on match or no match.
263273

274+
You could do *any* of the things that are typically done with HTML forms &mdash; handle usernames and passwords, write new data to a database, create a quiz, etc.
275+
264276
The final line in the route function calls the template *index.html* and passes three variables to it:
265277

266278
```python
@@ -273,26 +285,24 @@ return render_template('index.html', names=names, form=form, message=message)
273285

274286
Adding **Flask-Bootstrap** ensures that we can build mobile-friendly forms with a minimum amount of effort.
275287

276-
Note that it is possible to build a customized form layout using Bootstrap 3 styles in a Flask template, or to build a custom form with no Bootstrap styles. In either case, you cannot use `{{ wtf.quick_form(form) }}` but would instead write out all the form code in your Flask template as you would in a normal HTML file. To take advantage of WTForms, you would still create the form class with `FlaskForm` in the same way as shown above.
288+
Note that it is possible to build a customized form layout using Bootstrap 4 styles in a Flask template, or to build a custom form with no Bootstrap styles. In either case, you cannot use `{{ wtf.quick_form(form) }}` but would instead write out all the form code in your Flask template as you would in a normal HTML file. To take advantage of WTForms, you would still create the form class with `FlaskForm` in the same way as shown above.
277289

278-
**IMPORTANT:** In early 2018, Bootstrap 4 replaced Bootstrap 3. The differences are significant; names and usage of styles have changed. For the time being, Flask-Bootstrap uses Bootstrap 3.3.7, so if you're writing Bootstrap styles into a Flask template, it is imperative that you use the [Bootstrap 3 documentation](https://getbootstrap.com/docs/3.3/css/).
290+
**IMPORTANT:** Note that you are using Bootstrap 4 if you installed with `pip3 install Flask-Bootstrap4`. In early 2018, Bootstrap 4 replaced Bootstrap 3. The differences are significant; names and usage of styles have changed. Refer to the [Bootstrap 4 documentation](https://getbootstrap.com/docs/4.3/layout/grid/) for correct usage of Bootstrap styles.
279291

280292
## Resources
281293

282-
* [Sending form data](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data) &ndash; how web browsers interact with servers; request/response
294+
* [Sending form data](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data) &mdash; how web browsers interact with servers; request/response
283295

284-
* [Flask-WTF documentation](https://flask-wtf.readthedocs.io/en/latest/index.html)
296+
* [Flask-WTF documentation](http://flask.pocoo.org/docs/1.0/patterns/wtforms/)
285297

286-
* [Complete WTForms documentation](https://wtforms.readthedocs.io/en/latest/index.html)
298+
* [Complete WTForms documentation](https://wtforms.readthedocs.io/en/stable/)
287299

288300
* [Flask-Bootstrap documentation](https://pythonhosted.org/Flask-Bootstrap/)
289301

290302
If you want to view the Bootstrap templates installed by Flask-Bootstrap, here's how:
291303

292304
<img src="../images/location-flask-bootstrap.png" alt="Location of Flask-Bootstrap">
293305

294-
<img src="../images/flask-bootstrap-templates.png" alt="Flask-Bootstrap template files" width="40%">
295-
296-
By viewing *base.html* in *templates/bootstrap,* you can find the Jinja2 directives that surround the HEAD, list of attached CSS files, footer area, etc. You can then use those directives in your own templates for finer control.
306+
<img src="../images/flask-bootstrap-templates.png" alt="Flask-Bootstrap template files" width=350>
297307

298-
Note that Flask-Bootstrap uses Bootstrap 3.x, not Bootstrap 4.
308+
By viewing *base.html* in *templates/bootstrap,* you can find the Jinja2 directives that surround the HEAD, list of attached CSS files, footer area, etc. You can then use those directives in your own templates for finer control. Or just [see the "Templates" section here for examples](https://pythonhosted.org/Flask-Bootstrap/basic-usage.html) of how to set up a Flask template that uses Bootstrap.

0 commit comments

Comments
 (0)