Skip to content
Snippets Groups Projects
README.md 6.68 KiB
Newer Older
  • Learn to ignore specific revisions
  • Alex's avatar
    Alex committed
    # Python3 Flask Template
    
    A started template for Flask web apps using **Python 3.8**. This started template includes:
    
    - Dynamic frontend templates (not React)
    - Database support
    - Imperial LDAP user authentication
    - Multiple environments (development and production)
    - DoC Materials and Imperial Panopto API functionality
    
    
    This template is useful if you would like to create a backend REST API, optionally coupled with a simple dynamic frontend.
    
    ## Getting started
    
    Once you have created your new app, take a few minutes to look through the files to familiarise yourself with the project structure.
    
    - `app.py` : entry point to the Flask app
    - `templates/` : contains the frontend dynamic HTML files
    - `static/` : contains the static frontend assets (images, stylesheets and scripts)
    - `blueprints/` : contains all the application routes
    - `models/` : contains all the database models/schemas
    - `database/` : contains the database creation
    - `config/` : contains the app settings for the different environments
    
    **The first change you should make** is to set the `APP_NAME` variable in `config/config.py` to whatever you app's name is.
    
    To start the application locally, you can just run `python3 app.py` and this will launch the app on port 5000 (by default).
    You will notice a message in the console saying: 
    
    `WARNING: Could not connect to the given database URL!`
    
    To fix this, you should set the environment variable DATABASE_URL accordingly. If you have PostgreSQL running locally, you can use that. Alternatively, you could use SQLite which is much simpler and does not require installation, for example, by running ```export DATABASE_URL="sqlite:///dev.db"```
    
    If you do not want to use a database yet, you can ignore this warning and delete any routes that interact with the database.
    
    If you navigate to `http://localhost:5000`, you will see the response created by the route defined in `blueprints/home.py`.
    
    You will also notice the lines `Environment: production` and `Debug mode: off` when the Flask application starts in the console. To enable debug mode, you must set the environment variable `ENV` to `dev`, ie: `export ENV=dev` (see `config/config.py` for more details on different environments).
    
    ## Tutorial 1: Adding a new route
    
    In this template, we have provided several routes in the ```blueprints/``` directory. For example, we have provided all authentication-related routes (such as login and logout) in the ```auth.py```. It is good practice to group your routes logically and create new blueprints if necessary.
    
    To create a new blueprint, create a new file with the name of your blueprint and add:
    
    ```python
    from flask import Blueprint
    
    my_new_blueprint = Blueprint("new_bp", __name__, url_prefix="/new_bp")
    ```
    
    You can then add a new route to that blueprint as follows:
    
    ```python
    @my_new_blueprint.route("/hello")
    def hello():
        return "Hello!"
    ```
    
    Finally and importantly, you must **register the blueprint** with the Flask application. To do this, go to ```app.py``` and register the blueprint in the same style the existing code does so.
    
    Your new route will now be accessible at ```/new_bp/hello```.
    
    
    ## Tutorial 2: Adding database interaction
    
    An important part of web app development is adding database support. If you ticked the "Include DB" option when creating the app, you will have automatically received a PostgreSQL database. You can get the connection string on the dashboard and connecting to the database using it to verify that you do indeed have a database.
    
    For local development, you should either use an SQLite db or install PostgreSQL, and set the ```DATABASE_URL``` environment variable as explained in the Getting Started section.
    
    ### Defining database schemas
    
    When working with relational databases, you must define **schemas** (models) for your tables. For example, if you are developing a web app where users can write blog posts, you may want to define a schema for a blog post and a user.
    
    To do this, you can create new schemas/models in the ```models/``` directory and create a new file. In this template, we have an ```Entity``` model which has a primary key ID, a name which is a string and an age which is an int.
    
    For the blog example, let's create a schema for a blog post. Create a file called ```post.py``` and add:
    
    ```python
    from database.db import db
    
    class Post(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        title = db.Column(db.String(120), unique=False, nullable=False)
        text = db.Column(db.Test, unique=False, nullable=False)
    ```
    
    You then need to make sure the database will create the relevant tables in the database. Go to ```app.py``` and import your model here:
    
    ```python
    # Import all your database models just like below:
    with app.app_context():
        from models.entity import Entity
        if app.config["SQLALCHEMY_DATABASE_URI"]:
            db.create_all()
    ```
    
    For more on schemas using SQL-Alchemy, [read here](https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/).
    
    ### Querying the database
    
    You can now use your database to create, read, update or delete records using the SQL-Alchemy package. For example, if we want to create a new Post and add it to the database, we can do something like:
    
    ```python
    from database.db import db
    
    post = db.session.query(Post).filter_by(title="My article").first()
    
    new_post = Post(title="A new article!", text="This is my amazing article, I hope you enjoyed it.")
    db.session.add(new_post)
    db.session.commit()
    ```
    
    For more examples, please read around the [SQL-Alchemy package](https://flask-sqlalchemy.palletsprojects.com/en/2.x/).
    
    
    ### Running migrations and updating schemas
    
    To migrate your production database, you should connect to it directly using the connection string available in the PaaS dashboard with a tool like [PgAdmin](https://www.pgadmin.org/) (or connecting to it using your terminal), and run the relevant queries there.
    
    ## Tutorial 3: Configuring a test environment
    
    Often, we want to test that our web application is working as expected by writing a series of tests. For a simple example, you can view the code in the ```tests/``` directory.
    
    Unit testing a web app can be difficult, so we can test simple behaviours such as checking that a particular route is working as expected. We can setup a dummy app using a test configuration, as demonstrated in the ```test_home.py``` file. You can add more tests in this directory by making new functions with the ```test_``` prefix.
    
    To run these tests, you can run ```python -m pytest tests``` from the root directory. You should always run these tests before pushing/deploying new code, as they can catch out bugs. In fact, the CI/CD pipeline will run the tests for you, meaning that if a test fails, the pipeline will stop and your code won't be deployed until you fix the code causing the tests to fail.