Morepath codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API.
This codebase was created to demonstrate a fully fledged fullstack application built with Morepath, using Pony object-relational mapper, including CRUD operations, authentication, routing, pagination, and more.
We've gone to great lengths to adhere to the Morepath community styleguides & best practices.
For more information on how to this works with other frontends/backends, head over to the RealWorld repo.
A demo conduit-morepath backend server is running at https://conduit.yacoma.it/api.
Clone this repo and adjust the settings in the settings folder. Remember to change the master_secret.
From inside the project directory create a clean Python environment with virtualenv and activate it:
$ virtualenv -p python3 env
$ source env/bin/activate
After this you can install the package including dependencies using:
(env) $ pip install -Ue .
Once that is done you can start the server:
(env) $ gunicorn conduit.run
You can access the conduit server at http://localhost:8000/api.
You can also start the server on another host/port:
(env) $ gunicorn --bind=example.com:3000 conduit.run
- Programming language: Python 3
- Web framework: Morepath
- Object-Relational Mapper: PonyORM
- Authentication: JSON Web Token (JWT)
- Validation: Cerberus
- CORS support: more.cors
- Creating slugs from article titles: awesome-slugify
- Password hashing: Argon2
- WSGI HTTP Server: gunicorn
The core application under the conduit
folder contains:
run.py
- The entry point to our application. It sets up the database and provides a WSGI factory which can be used by a WSGI HTTP Server like gunicorn to run the application.app.py
- Sets up the core App and merges the AuthApp, the BlogApp and the PonyApp from more.pony in by subclassing from them. It also creates a ProductionApp and a TestApp, which are used instead depending on theRUN_ENV
environment variable.permissions.py
- Sets up the permissions and permission rules used to protect the views.database.py
- Just creates an instance of the PonyORMDatabase
.error_view.py
- Defines the handling of the CerberusValidationError
. For details see below.utils.py
- Some utility scripts. Here for transforming from datetime to ISO format and back.auth/
- Folder contains the AuthApp.blog/
- Folder contains the BlogApp.settings/
- Folder contains the default settings and the settings for production and testing in YAML format.test/
- Folder contains the unit tests.
The subapplication folders auth/
and blog/
contain:
app.py
- Defines the App.model.py
- Creates the models extended from PonyORM'sdb.Entity
.collection.py
- Sets up the collection models.path.py
- Defines the paths depending on the model.view.py
- Creates the views depending on the model.schema.yml
- Contains the schemas used by Cerberus in YAML format.validator.py
- Contains custom validators used by Cerberus (only inauth
).
For validating the incoming JSON data on requests we use Cerberus.
The Cerberus schemas are defined in schema.yml
inside the app folders (auth/
and blog/
).
You can also add custom validators, e.g. the EmailValidator
defined in auth/validator.py
.
Cerberus returns an ValidationError
. How to handle the response including returning a 422 status code
and formatting the view is defined in error_view.py
.
We use the
Morepath identity policy
provided by more.jwtauth
which allows authentication of request through the
JWT token
in the Authorization
header.
For installing the test suite and running the tests use:
(env) $ pip install -Ur requirements/develop.txt
(env) $ py.test
To check for test coverage:
(env) $ py.test --cov
The example App ships with 100% test coverage.
To check if your code is conform with PEP8:
(env) $ flake8 conduit setup.py
You can also run tox locally if you have installed Python 3.5 or/and Python 3.6:
(env) $ tox
We're using Black for formatting the code and it's recommended to install the pre-commit hook for Black integration before committing:
$ pre-commit install
To format the code with the Black Code Formatter run in the root directory:
$ black .
Black has also integration for the most popular editors.
On Debian/Ubuntu you can install them as superuser with:
$ apt-get install nginx supervisor make
We use a post-receive
git hook to publish the repository on the production
server. He triggers on every push to the git repo on the server.
The post-receive
hook uses the path defined in the prod_path
variable. Make sure that this path exists on the server before pushing
the first time.
The hook triggers make deploylive
which is defined in Makefile
. This
install the dependencies and build the App.
The deploy/conf
directory contains samples for git hook and server
configuration with gunicord behind a nginx reverse proxy. For monitoring
and controlling gunicord we use supervisor.
- git/hooks/post-receive - put this in the
hooks
directory of your bare git repository on the server and make sure it is executable. - web/nginx.conf - the nginx configuration.
- web/supervisord.conf - the supervisor configuration for gunicorn.
- web/gunicorn.sample.conf.py - Gunicorn configuration, should be moved
to
web/gunicorn.sample.py
after configuring.
The samples have to be configured by replacing the placeholders indicated by [PLACEHOLDER].
The following placeholders are used:
- [PATH TO APP] - absolute path to the app folder on the server
- [IP] - IP address of the server
- [PORT] - port on which the Gunicorn WSGI server should run (remember to open this TCP port in your firewall)
- [SERVERNAME] - servername which is normally the base URL of the server
- [PATH TO LOG] - absolute path to HTTP log without file extension
- [PATH TO GUNICORN LOG] - absolute path to Gunicorn log without file extension
- [PATH TO CERTIFICATE] - absolute path to SSL certificate file
- [PATH TO CERTIFICATE KEY] - absolute path to SSL certificate key file
- [PATH TO CLIENT APP] - absolute path to client app you want to serve
Optionally you can also serve a conduit client like the Cerebral Example App together with the Morepath backend.
- In nginx.conf add a root location with the path to your client build. It can be in a different directory then the Morepath backend.
- Add a
post-receive
git hook to your client repo similar to the one we use for the backend.#!/bin/bash # set -x app_path="[PATH TO CLIENT APP]" while read oldrev newrev ref do branch=`echo $ref | cut -d/ -f3` if [[ "master" == "$branch" ]]; then git --work-tree=$app_path checkout -f $branch cd $app_path make deploylive echo 'Changes pushed live.' fi done
- Create a simple Makefile to build the client. Remember to put a tab character
at the beginning of every recipe line!
.PHONY: deploylive deploylive: rm -rf node_modules npm install npm run build
PonyORM supports SQLite, PostgreSQL, MySQL/MariaDB and Oracle. In the example App we use Postgres in production and SQLite for development and testing.
When you want to use another database then SQLite you have to first create a database for conduit-morepath on the server.
Then configure conduit/settings/production.yml
according
to the database setup.