Postman API Collection
Our fidesops Postman Collection can be used to test fidesops endpoints.
Follow our Using Postman guide to learn more about the how to use the collection.
We define API URLs for specific API versions as constants within
v1 can be substituted for that particular API version), then import those URLs into their specific API views. Since we are on the first version, there is no clear precedent set for overriding URLs between versions yet. The most likely change is that we'll override the
APIRouter class instantiation with a different base path (ie.
/api/v2 instead of
/api/v1). For example:
would both resolve as
Database and Models
The ORM -- SQLAlchemy
SQLAlchemy is an Object Relational Mapper, allowing us to avoid writing direct database queries within our codebase, and access the database via Python code instead. The ORM provides an additional configuration layer allowing user-defined Python classes to be mapped to database tables and other constructs, as well as an object persistence mechanism known as the
Session. Some common uses cases are listed below, for a more comprehensive guide see: https://docs.sqlalchemy.org/en/14/tutorial/index.html
Database tables are defined with model classes. Model files should live in
src/app/models/. Individual model classes must inherit from our custom base class at
app.db.base_class.Base to ensure uniformity within the database. Multiple models per file are encouraged so long as they fit the same logical delineation within the project. An example model declaration is added below. For a comprehensive guide see: https://docs.sqlalchemy.org/en/14/orm/mapping_styles.html#declarative-mapping
You should also import your model in src/fidesops/db/base.py so it is visible for alembic.
1 2 3 4 5 6 7
When models are added to the project, we must then add them to the database in a recordable and repeatable fashion using migrations.
Using the database via models
Once you've added database tables via project models, you're ready to read, write and update them via Python code. Some examples of common use cases here are listed below. Official documentation is here: https://docs.sqlalchemy.org/en/14/orm/query.html#sqlalchemy.orm.Query.
- Import our application's database session:
from fidesops.ops.db.session import get_db_session
- Instantiate the database interaction object:
- Create a new row in a table:
1 2 3 4 5 6 7 8 9
- Fetch all objects in a table:
users = db.query(User).all()
- Fetch all objects in a table that meet some criteria:
active_users = db.query(User).filter(User.is_active == True)
- Get a specific row in a table:
user = db.query(User).get(User.email == "email@example.com")
- Update a specific row in a table:
1 2 3 4
Connecting to the database
When you run
nox -s dev, the database will be spun up in a Docker container with port
5432 exposed on localhost. You can connect to it using the credentials found in
- Username: see
- Password: see
Some common Alembic commands are listed below. For a comprehensive guide see: https://alembic.sqlalchemy.org/en/latest/tutorial.html.
The commands will need to be run inside a shell on your Docker containers, which can be opened with
nox -s dev -- shell.
- Migrate your database to the latest state:
alembic upgrade head
- Get revision id of previous migration:
- Automatically generate a new migration:
alembic revision --autogenerate -m "<a message describing your changes>"
- Create a new migration file to manually fill out:
alembic revision -m "<a message describing your changes>"
- Migrate your database to a specific state
alembic upgrade <revision-id>or
alembic downgrade <revision-id>, (or if you want to be smart
alembic upgrade <revision-id> || alembic downgrade <revision-id>is handy when you don't know whether the target revision is an upgrade or downgrade)
- NB. You can find the
revision-idinside each migration file in
alembic/versions/on line 3 next to
Revision ID: ...
When working on a PR with a migration, ensure that
down_revision in the generated migration file correctly references the previous migration before submitting/merging the PR.
Our preference for exception handling is by overriding the nearest sensible error, for example:
1 2 3 4 5 6
General debugging -- pdb
The project uses
pdb for debugging as a
dev-requirement. You can set breakpoints with
pdb in much the same way you'd set them using
import pdb; pdb.set_trace() into the line where you want the breakpoint to set, then run your Python code.
Occasionally when developing you'll run into issues where it's beneficial to remove all existing Docker instances in order to recreate them based on some updated spec. Some commands to do this are below:
- Stop all running containers:
- Delete all local containers:
docker rm -f $(docker ps -a -q)
- Delete all local Docker volumes:
docker volume rm $(docker volume ls -q)
- Remove temp. files, installed dependencies, all local Docker containers and all local Docker volumes:
nox -s clean
- Delete all stopped containers, all networks not used by a container, all dangling images, and all build cache:
docker system prune
- Recreate the project:
nox -s "build(dev)"