Newer
Older
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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)
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
- `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.
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
## Tutorial 2: Adding database interaction
## Tutorial 3: Configuring a test environment
# Flask Migrations and Databases
A table in flask is called a "Model", all models need to extend "db.Model". You have been provided with two models, "Person" and "PhoneNumber" which is a 1-many relationship; a "Person" can be many "PhoneNumber".
## Setup
It is very useful to have some view of your database as you develop to see whether migrations have actually been performed, and to view your data. We recommend "PgAdmin" if you are going to use PostgreSQL connection strings.
Download link: https://www.pgadmin.org/download/
### Tutorial: Setup remote connection to database with PgAdmin
1. Right-click on "Servers".
2. Create => Server...
4. Go to "Connection"
5. Enter for "Host" the IP address (or hostname) of the server which runs PostgreSQL Server.
6. Enter the "Port", default is `5432`.
7. Enter the "Username", default is `postgres`.
8. Enter the "Password", no default, the server should've been setup with one.
9. Hit "Save".
### Tutorial: Create a database remotely with PgAdmin
1. Click the server you remotely connected to in the previous tutorial.
2. Right-click on "Databases".
3. Create two new databases: one called "first_db_prod", and another called "first_db_debug".
4. Form two connection strings using the format below:
`postgresql://<username>:<password>@<host>:<port>/<db_name>`
Example: `postgresql://postgres:sAmPlE>@82.36.12.1:5432/first_db`
5. Go to the next tutorial below.
### Tutorial: connect to your database
You will need to specify the database connection strings for development ("debug" or "dev") and for production ("prod").
1. Navigate to: `config/config.py`
2. CTRL + F, then type in: db_configs
3. You'll see a single entry with two specified environment variables.
4. For each environment variable, configure your computer to set these as user environment variables. In Windows do the following: Control Panel => Search: environment => Edit the environment variables for your account => "New" => ...
5. Reload your IDE so the environment variable take effect.
Notes
- To speed up development you may use the "force" optional parameter variants, however this is discouraged as it exposes your connection string in your git repository.
- The two connection strings must NOT be the same!
- Do not use SQLite if you plan to make use of flask migrations.
- If you do add another database, make sure you add a static variable as well under the "DB Bindings" region, as you'll need to be able to reference this binding from the outside when creating models for the database this binding will be for.
- All binding key names must be unique; they are the identifiers Flask uses to uniquely identify each database amongst all other databases in your application.
## Adding a new table
1. Navigate to: `models`; you're models should all be made here.
2. Modify the "models" `"__init__.py"` to import your model, otherwise flask will not see it and not be able to migrate it.
3. Run a new migration when you're happy with your model to auto add the table for you.
When you run a migration for the first time the `migrations` directory will be constructed.
The `migrations` directory contains all migrations you have performed on every database this app uses. It contains the subdirectories `dev` and `prod`, then subdirectories identified by the binding keys used.
You have been provided with the binding `first_db`. Running a migration will result in the following path being accessible:
`migrations/dev/first_db/`
It is very important that you do not delete anything from this directory, since flask migrate will also store a migration history in correspondance to the directory's contents in your database, under the `alembic` table.
### Tutorial: running an "upgrade" migration script
Flask migrate will automatically generate a migration script based on the differences between your database represented in flask (this application) and the actual database. It may be incorrect, or may not fully complete the migration you want. To resolve this, you should check the migration script, and verify it does what you want it to do.
1. Navigate to: `models/first_db_models/phone_number.py`
2. It is very useful for rows in a database to have a `created_at` attribute so you know when the row was first inserted. Comment out the new under the TODO, and remove the TODO.
3. Edit the file: `RunUpgradeMigration`
4. Change the value of the 3rd argument to either `dev` or `prod`.
5. Change the value of the 4th argument to be the binding key name of the database you want to migrate. Since "PhoneNumber" is a model that exists in the database bound to the binding key name "first_db", change the value to "first_db".
6. Save the file, then run it.
7. Navigate to: `migrations/dev/first_db/versions`
8. You should see a new python file created in here under some hash code, open the file.
9. Verify the file is doing an `add_column` operation in the `upgrade` method.
10. Complete the migration by pressing ENTER.
11. Repeat for the other database, i.e.: if you migrated on `dev`, then you should also migrate on `prod` at some point.
### Tutorial: running an "downgrade" migration script
Example: you performed an "upgrade" migration but realize that it wasn't what you wanted, or could improve the column definition, for example you realize "phone_number" should not be a column part of "Person" but rather a separate table called "PhoneNumber" with a 1-many relation.
1. Edit `RunDowngradeMigration`.
2. Change the value of the 3rd argument to either `dev` or `prod`.
3. Change the value of the 4th argument to be the binding key name of the database you want to migrate. Since `PhoneNumber` is a model that exists in the database bound to the binding key name `first_db`, change the value to `first_db`.
4. Save the file, then run it.
## Troubleshooting
### Consistency violation, cannot find version
Delete/drop the `alembic` table from the database, and delete the associated migration directory for this table only.