<style> .present { text-align: left; } </style> --- ###### tags: `Week 18` `W18D2` --- # More about Flask ## Week 18 Day 2 --- ## Review from yesterday... - pipenv and virtual environment - .flaskenv vs .env - Config class - Routes! - decorators for the url path & methods - view functions - templating with Jinja - template tags - {{ }} for display/resnder/print - {% %} for doing stuff (loops or conditionals) --- ## Templating with Jinja --- ### Jinja - Jinja is an HTML templating language (similar to Pug) - Add the Jinja package to your application (Optional, flask comes with Jinja as a dependency) - `pipenv install Jinja2` - Flask looks for HTML templates in the `templates` folder inside the `app` package - Create a `templates` folder within your application - In `templates`, create HTML files that you would like your routes to render --- ### Rendering Templates - In your app, import `render_template` from `flask`. - `render_template` renders an HTML page using the Jinja template engine - Instead of returning HTML strings directly, call `render_template`, passing the name of the HTML file you would like to render ```python= @app.route('/') def index(): return render_template('index.html') ``` --- ### Rendering Templates with Arguments - We can pass objects from our routes to `render_template` for use in our HTML files. - Objects are passed as kwargs, where the key is the name of the item referenced in the HTML file, and the value is the object itself from the route. ```python= @app.route('/') def index(): return render_template('index.html', display_item=value) ``` --- ### Redirecting to Another Route - We can redirect to another route with `redirect()` - `redirect()` takes a string for the route location to redirect to and an optional default status code if the redirection is unsuccessful ```python= @app.route('/') def index(): return redirect('/all', 404) ``` --- ### Accessing Objects and Evaluating Code - In our HTML files, we use `{{ display_item }}` to access objects that were passed in as kwargs to `render_template` - We use the `{% %}` syntax to evaluate code within an HTML file ```python= {% for x in items %} {% endfor %} ``` ```python= {% if condition_a %} {% elif condition_b %} {% else condition_c %} {% endif %} ``` --- ### Extending and Including Content We can use `extends` to reuse a base template in other HTML files: ```python= {% extends "base.html" %} ``` The base template can include a placeholder for content from other HTML files: ```python= {% block content %} {% endblock %} ``` Our other HTML files use the same tags to fill in that content. We can reuse small templates with `include`: ```python= {% include "other_template.html" %} ``` --- ## Routing with Flask Blueprints --- ### Blueprints Blueprints allow us to organize our code by breaking our routes into individual components, much like Routers did for us in Express. --- ### Creating a Blueprint - Import the Blueprint package from Flask: `from flask import Blueprint` - Construct a Blueprint with the following arguments: - A name for the Blueprint - The name of the file where it is defined (use `__name__` to use the current file name) - A `url_prefix`, which will be prepended to all routes associated with this Blueprint ```python= from flask import Blueprint books_router = Blueprint('books', __name__, url_prefix='/books') ``` --- ### Use the Flask Blueprint to make routes - The `@blueprint_name.route` decorator allows us to define routes to associate with our Blueprint - Exactly like we would use it for the base `app` routes in our main file ```python= # In the routes/books.py from flask import Blueprint books_router = Blueprint('books', __name__, url_prefix='/books') @books_router.route('/') def book_index(): # Show all the books ``` --- ### Register the Flask Blueprint with the Flask application - To connect our Blueprint to our app, we import the module that it is defined in. - Invoke the app's `register_blueprint` method with a reference to the Blueprint instance as an argument. ```python= from flask import Flask from book_app.routes import books_router # assuming we have a __init__.py in routes app = Flask(__name__) app.register_blueprint(books_router) ``` --- ## Lecture Videos (26 min) Watch: - Flask Routing (09:15) - Jinja2 (13:57) - Flask Blueprints (07:36) --- ### Creating Forms with WTForms You must have a SECRET_KEY in your app configuration for CSRF token validation to be successful - Create a forms directory and initialize it as a module with a `__init__.py` - `pipenv install wtforms flask-wtf` - `from flask_wtf import FlaskForm` - Define form classes in the forms module - Form classes will inherit from `FlaskForm` - From `wtforms` import field types for your form and any built-in validators --- ### Creating Forms with WTForms ```python= from flask_wtf import FlaskForm from wtforms import StringField, SelectField, SubmitField from wtforms.validators import DataRequired class NewBookForm(FlaskForm): title = StringField("Title", validators=[DataRequired()]) rating = SelectField( "Rating", choices=["New favorite", "Great", "Good", "Underwhelming", "Bad", "Horrible"] ) submit = SubmitField("Add Book") ``` --- ### Field Types - Check out the `wtforms` [docs](https://wtforms.readthedocs.io/en/2.3.x/fields/#basic-fields) to understand different field types for your forms - We can import validators into our form from `wtforms.validators` ([documentation](https://wtforms.readthedocs.io/en/2.3.x/validators/)) --- ### Handling Get and Post Routes In our app, we can handle: - `GET` request for the form - `POST` request with valid data - `POST` request with invalid data --- ### GET Route ```python= @books_router.route('/new_book', methods=["GET"]) def add_book(): form = NewBookForm() return render_template("new_book.html", form=form) ``` --- ### Form Error handling - Invoking `validate_on_submit` on our form instance will return `True` if the `POST` had no validation error. - Once validated we can use `form.data` to access the data dictionary - If the form was `POST`ed with errors, `validate_on_submit` will return `False` - If not validated we can key into `form.errors` to access the errors dictionary --- ### POST Route ```python= @books_router.route('/new_book', methods=["GET", "POST"]) def add_book(): form = NewBookForm() if form.validate_on_submit(): title = form.data['title'] with psycopg2.connect(**CONNECTION_PARAMETERS) as conn: with conn.cursor() as curs: curs.execute( """ INSERT INTO books (name) VALUES (%(title)s) """, { "title": title } ) return redirect('/books/all') if form.errors: return form.errors return render_template("new_book.html", form=form) ``` --- ### Project Time! Today's projects are - Tweeter: Twitter like clone to practices, routes, forms, and templates - Calendar This: data-driven calendar application
{"metaMigratedAt":"2023-06-17T00:24:32.946Z","metaMigratedFrom":"Content","title":"More about Flask","breaks":true,"description":"Jinja is an HTML templating language (similar to Pug)","contributors":"[{\"id\":\"dafd1858-850b-4d12-9d53-a1ac5e891cf8\",\"add\":400,\"del\":36},{\"id\":\"a6f34c0b-3567-4ed5-ba81-c2299c2d9369\",\"add\":6967,\"del\":0},{\"id\":\"bbda4bdc-50a5-429e-9073-d74141f277f3\",\"add\":62,\"del\":78}]"}
    692 views
   owned this note