Commit ef4562c4 authored by Alex's avatar Alex
Browse files

Completed writing the tutorial in the readme

parent 7ece46d7
Pipeline #217249 passed with stage
in 1 minute and 5 seconds
......@@ -6,7 +6,6 @@ A started template for Flask web apps using **Python 3.8**. This started templat
- 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.
......@@ -19,7 +18,7 @@ Once you have created your new app, take a few minutes to look through the files
- `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
- `models/` : contains all the database models/schemas
- `database/` : contains the database creation
- `config/` : contains the app settings for the different environments
......@@ -30,7 +29,7 @@ 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.
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.
......@@ -38,13 +37,92 @@ If you navigate to `http://localhost:5000`, you will see the response created by
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).
In order to use the Panopto functionality, you must create a Panopto API client and set the client id and secret in app.py. Instructions to do that are [here](https://gitlab.doc.ic.ac.uk/paas-packages/imperial_panopto/-/blob/master/README.md). Go to /panopto_example to see the panopto example route.
## 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.
## Tutorial 3: Configuring a test environment
\ No newline at end of file
......@@ -28,7 +28,7 @@ imperial_panopto.set_panopto_is_dev(ENV != 'prod')
db.init_app(app)
# TODO Find a workaround for migrations/db.create_all()
# Import all your database models just like below:
with app.app_context():
from models.entity import Entity
if app.config["SQLALCHEMY_DATABASE_URI"]:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment