Een afbeelding die de combinatie van FastAPI, Python en Docker voor één project template laat zien.

FastAPI Project Template

Een FastAPI Python-projecttemplate met CI/CD, Docker, een Makefile, unit- en integratietests en linting.

Technologies
Python
Make
Docker
Poetry
SQLAlchemy
Alembic
GitHub Actions
FastAPI

Introductie

FastAPI is een zeer populair lichtgewicht framework om API’s op te zetten in Python. Het heeft de afgelopen jaren gestaag aan populariteit gewonnen, wat te danken is aan zowel de eenvoudige implementatie als de integratie met de datavalidatie- en type-annotatiebibliotheek Pydantic. Dit maakt het handmatig valideren van gebruikersgegevens overbodig. Het programmeren van endpoints is echter nog steeds slechts een klein onderdeel van het maken van API’s die klaar zijn voor productie. In deze blogpost delen we een opensource-template voor het opzetten van FastAPI-projecten, dat het resultaat is van het bouwen en implementeren van verschillende FastAPI-projecten in de loop der jaren.

Je kunt het template-project vinden met de volgende link: https://github.com/BiteStreams/fastapi-template.

Voordelen van een template

Dit template heeft de volgende voordelen:

  • De API is opgezet met Docker, wat het erg gemakkelijk maakt om te beginnen en het wisselen tussen projecten, besturingssystemen en machines vergemakkelijkt.
  • Het heeft een ingebouwde database, aangezien veel API’s vroeg of laat een database nodig hebben, en dit is niet standaard inbegrepen (op een nette manier) in FastAPI.
  • Poetry wordt gebruikt voor het bijhouden van requirements, een moderne tool die ook de meegebrachte requirements vergrendelt voor consistente builds samen met Docker.
  • Een meegeleverd Makefile, dat een ‘entrypoint’ is voor het project en het makkelijk maakt om op te starten/ontwikkelen zonder alle commando’s te onthouden.
  • We gebruiken meestal dezelfde targets voor al onze projecten, wat het gemakkelijker maakt van context te wisselen.
  • Een continuous integration opstelling met docker-compose en GitHub Actions, waardoor eenvoudige integratietests met Docker lokaal en in een CI-pijplijn mogelijk zijn.
  • Automatische code-linting en typecontrole om consistentie te garanderen (geen opmerkingen meer over regelafbrekingen in reviews!) en typefouten op te sporen.

Een combinatie van Docker & Make

Door Docker te gebruiken, is de ontwikkeling en implementatie van de code veel naadlozer verbonden en heeft het talrijke voordelen met weinig extra complexiteit. Docker maakt een lichtgewicht, reproduceerbare omgeving mogelijk om uw code en tests uit te voeren, omdat u uw omgeving met scripts kunt maken. Virtualisatie is natuurlijk geen nieuw idee (Vagrant, VirtualBox, enz.), maar Docker is een veel lichtere technologie, waardoor bijvoorbeeld ‘test’-containers mogelijk zijn. Testcontainers zijn erg krachtig, omdat de lichtgewicht Docker-containers het mogelijk maken om een reeks containers te bouwen die puur bedoeld zijn voor het uitvoeren van verschillende tests.

Dockerized tests

In dit template hebben we twee testsuites opgezet, een unit test suite en een integratietestsuite (voor grotere projecten kunnen er meer worden toegevoegd, zoals een end-to-end testsuite). Beide zijn gedockeriseerd, wat ze zo reproduceerbaar mogelijk maakt, terwijl ze toch efficiënt zijn. Omdat de tests containerized zijn, is het altijd mogelijk om het project uit te checken en onmiddellijk alle testsuites uit te voeren met behulp van make test.

Hier komt Make van pas. Het mooie hiervan is dat het een zeer intuïtieve entrypoint biedt voor de toepassing. Make stelt ons in staat om ons niet bezig te hoeven houden met alle specifieke argumenten (configuratie) die nodig zijn om de tests uit te voeren, en in plaats daarvan ons alleen te richten op wat we willen bereiken, namelijk het uitvoeren van de tests. Dit geldt ook voor andere commando’s die elk project typisch heeft, zoals make up, dat de applicatie start. Door deze commando’s consistent te houden, wordt het zeer eenvoudig om tussen projecten te schakelen en nieuwe mensen aan boord te brengen. Onboarding kan vaak een langdurig proces zijn wanneer bijvoorbeeld een specifieke set tools vereist is met specifieke softwareversies die moeten worden uitgevoerd met specifieke argumenten, en deze oplossing is bedoeld om dat pijnpunt op te lossen.

CI/CD Pipelines met GitHub Actions

Een ander voordeel van het gebruik van Docker en Make komt naar voren bij het bekijken van het opzetten van CI/CD-pipelines. CI/CD-pipelines hebben tal van voordelen, zoals kortere cyclustijden, minder bugs in de code en snellere ontwikkeling. In het template hebben we al een (zeer eenvoudige) CI-pipeline opgenomen om de tests in het project uit te voeren en de code te ‘linten’.

Aangezien het make commando direct werkt, kunnen we het feitelijk direct gebruiken in onze CI-pipeline! Dit is geweldig, omdat we vaak zien dat CI/CD-pipelines zeer specifieke shell-scripts vereisen om alles te laten werken. Dit heeft als nadeel dat het niet reproduceerbaar is zoals een ontwikkelaar werkt: omdat hij of zij de GitHub Actions niet lokaal kan uitvoeren (op het moment van schrijven zijn er enkele opties beschikbaar, maar die zijn niet geschikt voor deze use-case). Als extra voordeel voorkomt dit leveranciersafhankelijkheid door geen trucs te gebruiken van uw specifieke CI/CD-leverancier. Zoals hieronder wordt getoond, is de CI-pipeline opgezet met slechts één commando, make (en een afhankelijkheid van Docker).

 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

jobs:
  test:
    name: Run the test suite
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Run the tests
        run: make test

  checks:
    name: Check code
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Checks
        run: make check

Link naar de workflow

Aan de Slag

Zorg ervoor dat je aan de volgende requirements geïnstalleerd hebt:

  • Docker
  • Make (De meeste Linux-installaties hebben dit al, voor Windows moet je het controleren)

Om te beginnen, kloon eenvoudigweg het project (vervang my-project door een naam naar keuze):

1
$ git clone https://github.com/BiteStreams/fastapi-template my-project

Optioneel: Om een lokale kopie van de Python-omgeving te installeren (bijvoorbeeld voor code-aanvulling in je editor), kun je de poetry-omgeving installeren (op voorwaarde dat je de juiste Python-versie en poetry geïnstalleerd hebt) met poetry install.

Ga nu naar de projectmap vanaf de opdrachtregel. Alle commando’s moeten worden uitgevoerd vanuit de hoofdmap van het project. Het Make-bestand is het ‘entrypoint’ voor de tools in de applicatie, zodat je gemakkelijk verschillende commando’s kunt uitvoeren zonder de exacte argumenten te hoeven onthouden. Voer het volgende uit:

$ make help

Dit geeft een overzicht van de beschikbare commando’s:

 1up # Run the application
 2done: lint test # Prepare for a commit
 3test: utest itest  # Run unit and integration tests
 4check # Check the code base
 5lint # Check the code base, and fix it
 6clean_test # Clean up test containers
 7migrations # Generate a migration using alembic
 8migrate # Run migrations upgrade using alembic
 9downgrade # Run migrations downgrade using alembic
10help # Display this help message

De genoemde commando’s zijn bijvoorbeeld up, done, enzovoort, die je kunt aanroepen met make. Nu starten we de API met het up commando:

1
$ make up

Vervolgens kun je in een andere shell het schema bijwerken met behulp van alembic:

1
$ make migrate

Dat is alles, nu draait de app en is deze bereikbaar op localhost:5000/docs. Als je naar deze URL gaat, zou je de API-documentatie moeten zien: docs

Code-wijzigingen worden automatisch gedetecteerd met behulp van een Docker-volume.

Testen van FastAPI

Je kunt tests uitvoeren met de commando’s make utest en make itest. De tests worden gecontaineriseerd en de Docker-configuratie kan worden gevonden in de map .ci/. Ze zijn geschreven met behulp van Pytest. Je kunt de tests uitvoeren met:

1
$ make test

tests

Dit voert de integratie- en unit-tests uit. Als je de unit- en integratietests apart wilt uitvoeren, gebruik dan make itest om de integratietests uit te voeren en make utest om de unit-tests uit te voeren. Je zult merken dat make itest aanzienlijk langzamer is, omdat het ook een PostgreSQL-databasecontainer opstart voor de tests.

Relationele Database

Aangezien de meeste projecten een relationele database vereisen, hebben we ervoor gekozen er een standaard in te voegen. Omdat de database zich in een Docker-container bevindt, wordt deze automatisch gestart wanneer je de applicatie start. Er zijn ook opgenomen commando’s om migraties uit te voeren en te maken met behulp van alembic. De interactie van de code met PostgreSQL wordt gedaan met behulp van sqlalchemy, wat een industriestandaard is. We hebben ook een blogpost die 10 Tips voor het toevoegen van SQLAlchemy aan FastAPI geeft, waarin enkele implementatiekeuzes worden beschreven.

Om je database te migreren naar het nieuwste schema, voer je het volgende uit:

1
$ make migrate

Om een nieuwe migratie te maken nadat je enkele schema-wijzigingen hebt aangebracht, voer je het volgende uit en voeg je een bericht toe om te verduidelijken wat er is gewijzigd:

1
$ make migrations m="Migration message"

Linting

Om ervoor te zorgen dat iedereen code schrijft die mooi en consistent is opgemaakt, is het een goede keuze om linting-tools te gebruiken om je leven gemakkelijker te maken. Dit stelt een team in staat (tijdens het programmeren en bij het beoordelen van code) zich te concentreren op wat de code doet, in plaats van of er een juiste regelovergang aan het einde van het bestand is gemaakt of niet.

Om de code op ‘fouten’ te controleren, voer je het volgende uit:

1
$ make check

Dit controleert de code aan de hand van de volgende criteria:

  • black, dat de code controleert op opmaakfouten.
  • isort, dat Python-imports controleert (worden ze daadwerkelijk gebruikt) en hun volgorde.
  • mypy, dat de code controleert met behulp van statische type-analyse, wat in de loop van de tijd veel potentiële bugs voor ons heeft gevonden!

Als een van deze tools niet slaagt, wordt het commando afgebroken met een exitcode van 1. Om de fouten automatisch te corrigeren die door black en isort worden gedetecteerd, voer je het volgende uit:

1
$ make lint

linting Het kan handig zijn om een git pre-commit hook toe te voegen met make lint erin, of het als een hook toe te voegen in je favoriete IDE.

Black is geconfigureerd met een ‘line_length’ van 120, omdat dit is wat we prettig vinden. Je kunt al deze tools configureren in het bestand pyproject.toml in de hoofdmap.

FastAPI-tests in GitHub Actions

Tegenwoordig heeft elk serieus project CI (en CD) pipelines, en dit project ook! De pipeline is geïmplementeerd met GitHub Actions en de configuratie is zeer eenvoudig, omdat het dezelfde tools hergebruikt die we eerder hebben gebruikt. Aangezien de code standaard is geconfigureerd, wordt de CI-pipeline uitgevoerd telkens wanneer je een push doet naar de main branch. Je kunt dit eenvoudig wijzigen in het bestand code-integration.yml binnen de map .github/workflows.

De CI-pipeline voert make test en make check uit, net zoals je lokaal zou doen. Dit zorgt ervoor dat de code op de juiste wijze wordt getest en gecontroleerd.

Conclusie

We hopen dat deze sjabloon mensen kan helpen bij hun FastAPI-projecten! Deze structuur heeft ons geholpen bij het opzetten van meerdere van onze projecten en stelt ons in staat om snel nieuwe teamleden aan boord te krijgen. Het geweldige aan dit soort structuur is dat de Makefile-structuur niet afhankelijk is van FastAPI of zelfs Python. We hebben bijvoorbeeld dezelfde Makefile + Docker-structuur gebruikt voor enkele van onze Golang-projecten.

Oorspronkelijk is dit sjabloon gemaakt voor een presentatie over unit testing die we hebben gegeven tijdens de SharkTech Talks bij Start Up Village (SUV) in Amsterdam.

About the author

Maximilian Filtenborg

Maximilian is een liefhebber van machine learning, ervaren software-engineer en mede-oprichter van BiteStreams. In zijn vrije tijd luistert hij naar elektronische muziek en houdt hij zich bezig met fotografie en hiken.

Meer lezen

Verder Lezen

Enjoyed reading this post? Check out our other articles.

Heeft u een professionele data API nodig voor belangrijke inzichten? Contacteer ons nu

Wordt meer datagedreven met BiteStreams en laat de concurrentie achter je.

Contacteer ons