Back Office Low Code (backo)
Jump to Quickstart for a basic setup.
See Documentation for all details
What is backo
It aims at providing a simple and efficient way to create a backend application that exposes a set of RESTfull API routes for CRUD and more.
It is based on :
- Standard description of elements :
Collection(aka Table in SQL)Itemthe object in the collectionReferences cross collections (Ref and RefsList)- standard types (Int, String, Dict, Float, Bool, List, Tuple)
- custom types (inheritance)
- files
- standard attributes (required, default, ...)
- Standard API
- All routes for CRUD
- All routes for select (pagination, complex filtering)
- Connector to a standard Database or file (MongoDB, Sqlite3, ...)
No dedicated language, no configuration file : 100% python, Full programatic (you can change any value by a function with return a value, it is YOUR code).
Features
Full ORM in python
Backo is a ORM written in python. It is Database agnostic.
Backo use References to manage cardinalities
Api RestFull
Backo provide a complete restfull API for CRUD, with data validation testing, security check, error management.
It provides more routes than just CRUD :
- routes for checking,
- routes for mutipart (for file management)
- automatic openapi 3.1 structure
See Routing for details
Database handling
Backo can access to multiple database system (like SQlite3 or mongo). It can make cross references between different databases.
- Different types of databases (MongoDB, SQL, ...)
- Filtering / sorting transformation into the DB language
- can adapt to existing database with
Transformer - can integration in an existing SI
- mix different types of
DBHandlerperCollectionwith cross references
- mix different types of
- Structure coherence policies
- keep database coherence
- delete item, external collections
See Database handling for details
More than just schema
backo has an kind of extended schema description (like pydantic), but propose more features.
-
Complex constraints You can have fields with contraint function. Example : the field
salarymust be above 10000 if the fieldjobis doctor -
Computational fields You can have fields that are the result of a python function. Example : the field
ageis a computation of another field (date_of_birth) and datetime.now() -
Conditional fields Every time, you have fields that exists only in some cases. Example : The field
thesis_defense_dateexists only if the fieldjobis doctor -
File fields Files are managed like any other field. See File documentation for details.
-
Events You can add events on fields. You can trigg a function when the field
addresshas changed, when the object is deleted, loaded, ... or whatever
See fields for details
Low code
The main idea is to reduce the code you write, and focus on the business code.
| feature | backo | you | comment |
|---|---|---|---|
| Input Validation Testing | ✅ | ||
| Schema Validation Testing | ✅ | ||
| Security check | ✅ | ||
| Database consistency | ✅ | different policies | |
| Web server and API Restfull | ✅ | Done with Flask | |
| Authentication | ✔️ | ✅ | Code the auth, and give a JWT to backo |
| RBAC | ✅ | ✅ | business code : You just have to describe what you want (in python) |
| Security everywhere | ✅ | ✅ | business code : You can add rights on every objects, field... |
| Database(s) | ✅ | 🚀 | you can use mutiple databases and adapt to existing databases, with cross-references |
| Files | ✅ | files are just fields like others | |
| Compute a field | ✅ | 🚀 | you can add fields with are the result of a python function, and depend on other fields. Just write the function |
| Conditional fields | ✅ | 🚀 | you can have fields depending on others |
| Events | ✅ | 🚀 | every field can trigg and react on events |
| openapi | ✅ | The openapi 3.1 doc is generated from your code |
Short example
Here is a small example to see what looks like a backo code for one Collection.
See Coding to understand quickly how it works.
from Flast import flask
from backo import Backoffice, Collection, Item, String, Int, Dict, Ref, Datetime
from backo.file import File, FileSystemConnector
from backo.db import DBMongoConnector
# Define the Item
books_item = Item(
{
"title": String(require=True, default="No title", can_modify=modify_books_title_function),
'cover': File( require=True, mime_types=[ 'image/jpeg', 'image/png' ], work=FileSystemConnector( path="/path/to/store/the/file" ) ),
"pages": Int(),
"borrow": Dict(
{
"user": Ref(
coll="users",
field="$.rent.books",
),
"return_date": Datetime(),
"date": Datetime(),
},
),
}
)
# define the DBHandler
connector = DBMongoConnector(
connection_string="mongodb://...", collection="Books"
)
# define the Collection
books = Collection("books", books_item, connector)
myapp = Backoffice("media_library") # my backo
myapp.register_collection(books)
# set up the serveur
flask = Flask("my_media_library")
myapp.build_routes(flask) # build API routes
flask.run(host="0.0.0.0", port=5000) # start the web server
See the full example
Architecture
A single application
Scheme of a classical architecture (mono database), with Collections (aka Tables) all in the same DB.
flowchart LR
subgraph application
flask@{ shape: div-rect, label: "flask" }
subgraph backo
backoffice@{ shape: div-rect, label: "backoffice" }
coll1[collection 1]
coll2[collection 2]
coll3[collection 3]
DBHandler1[ DBHandler ]
DBHandler2[ DBHandler ]
DBHandler3[ DBHandler ]
end
DB1[(Database)]
end
client1[ client ] -. GET\nPOST\nPATCH\nDELETE .-> flask
client2[ client ] -. GET\nPOST\nPATCH\nDELETE .-> flask
flask <==> backoffice
backoffice <==>|"get_by_id()\ncreate()\nselect()\nupdate()"| coll1
backoffice <==> coll2
backoffice <==> coll3
coll1 <==>|"get()\ncreate()\nselect()\nsave()"| DBHandler1
DBHandler1 <-->|"SELECT * FROM WHERE"| DB1
coll2 <==> DBHandler2
DBHandler2 <--> DB1
coll3 <==> DBHandler3
DBHandler3 <--> DB1
Integration
Scheme of an architecture with Collections (aka Tables) dispatched in differents DB (not because you want to do that, but because databases already exists like that)
flowchart LR
subgraph application
flask@{ shape: div-rect, label: "flask" }
subgraph backo
backoffice@{ shape: div-rect, label: "backoffice" }
coll1[collection 1]
coll2[collection 2]
coll3[collection 3]
DBHandler1[ DBHandler ]
DBHandler2[ DBHandler ]
DBHandler3( DBRestFull )
end
DB1[(Database 1)]
end
client1[ client ] -. GET\nPOST\nPATCH\nDELETE .-> flask
client2[ client ] -. GET\nPOST\nPATCH\nDELETE .-> flask
flask <==> backoffice
backoffice <==>|"get_by_id()\ncreate()\nselect()\nupdate()"| coll1
backoffice <==> coll2
backoffice <==> coll3
coll1 <==>|"get()\ncreate()\nselect()\nsave()"| DBHandler1
DBHandler1 <-->|"SELECT * FROM WHERE"| DB1
coll2 <==> DBHandler2
DBHandler2 <-->|"coll.find().sort()"| DB2[(Database 2)]
coll3 <==> DBHandler3
DBHandler3 <-..->|GET\nPOST\nPATCH\nDELETE| DB3[external API]
Documentation and examples
We try to maintain a full comprehensive documentation
And some runnable examples runnable examples
About us
backo is developped and maintained by the engineers team of inria (especially Centre inria de l'Universite de Lorraine)
(Sorry some links are in french...)
Disclaimer
We want backo :
- to be and stay FOSS, event if some binding to non free databases (mongoDB...)
- to be under MIT Licence,
- to stay with minimum dependency from other packages. A light package.
- to be made without vibe coding : You can use IA for helping you, but without embedded agent in your IDE. Your prompt must start with "Explain me how ...". **The IA must enhance your knowledge **, not replace you.
Don't hesitate to contact us and contribute
Tests & co
For personal use only.
Legacy virtualenv workflow:
# all tests
python -m unittest tests
# or for a specific test
python -m unittest tests.TestDict.test_simple_type
# reformat
python -m black .
# pylint
pylint $(git ls-files '*.py')
# coverage
coverage run -m unittest tests
coverage html # report under htmlcov/index.html
firefox htmlcov/index.html
# docs
uv sync --all-extras --all-groups
cd docs
uv run make html
uv workflow:
uv sync --all-groups --all-extras
# all tests
uv run python -m unittest tests
# or for only some tests
uv run python -m unittest tests/test_bool.py
# or for a specific test
uv run python -m unittest tests.TestDict.test_simple_type
# reformat
uv run black .
# pylint
uv run pylint $(git ls-files '*.py')
# coverage
# for all tests
uv run coverage run -m unittest tests
# for a single tests suite
uv run coverage run -m unittest tests.MyTests
uv run coverage html # report under htmlcov/index.html
firefox htmlcov/index.html
Building a new release
For personal use only.
# Modify changelog
# modify pyproject.toml
git add -u
git commit -am 'preparing 0.0.x'
git push
git tag -a 0.0.x -m '0.0.x'
git push origin tag 0.0.x
# publish a new relase in github interface, based on tag
Metadata
Release files for backo 0.3.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| backo-0.3.9.tar.gz | 213.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| backo-0.3.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 319.2 kB
Release files / backo-0.3.9.tar.gz
| Download URL | backo-0.3.9.tar.gz |
|---|---|
| Size | 213.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0357d8b8569e508e6c9468b12a0cba43c4f6b461f646ef4e05fb67a34ac2bc04
|
|
BLAKE2b-256 checksum How to use checksums |
c52e3fa7a9b2ff29ea3854494d8728ca66ffc25ea632c6189bb944ee78e92134
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / backo-0.3.9-py3-none-any.whl
| Download URL | backo-0.3.9-py3-none-any.whl |
|---|---|
| Size | 106.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3f73b3e9ebda2a46792ccf68dca314f122b396953461d74f85f3f60503d4b0f7
|
|
BLAKE2b-256 checksum How to use checksums |
75d6d7b5b3abef5abb8f6177fc8c3b322b94fb824e3ff86a93620650708224c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Security for backo 0.3.9
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.