There are the usual config files in the root of the repo.
The "project root", containing settings.py
etc. Also an app, with models for users, organisations, and projects.
The app with models and views for viewing, downloading, creating, and updating codelists.
A directory containing one app per coding system. Each of these apps contains a coding_system.py
which defines a common interface, and an import_data.py
which contains
code for importing new data.
Each directory contains a README with information about the underlying data.
An app that holds information about coding system releases.
Each release of a coding system is imported into a separate sqlite database, and has a CodingSystemRelease
instance associated with it which allows us to identify the specific
release database to use to retrieve codes and terms for a codelist version..
A directory containing one app per mapping between coding systems. Each of these apps will have a common structure, which has not yet been codified.
Templates.
Resources for deployment. Deployment is via dokku (see deployment notes).
A place to put scripts to be run via runscript.
Production data is stored on dokku3 at /storage/
within the container layer
file system. This maps to /var/lib/dokku/data/storage/opencodelists
in the
host operating system's file system. See also deployment notes).
/storage/db.sqlite3
is the core Django database.
/storage/coding_systems
contains the coding system databases. These are
read-only. Refer to their README files for information on the source data and
creation process.
The core database is fully backed up daily on the local file system. Coding system databases are not backed up locally but can be recreated from source. Weekly backups of the droplets allow a restore of the file system.
The core database backups are located at /storage/backup/db
. They are created
by deploy/bin/backup.sh
scheduled via cron
as configured in app.json
.
Backups are taken via the sqlite3
.backup
command . These are effectively
copies of the database file. They are compressed to save space.
To restore from a backup, use the command-line tool to create a fresh temporary backup of the current state of the database (in case anything gones wrong), then restore from the decompressed backup file. On the production server:
dokku enter opencodelists
sqlite3 /storage/db.sqlite3 ".backup /storage/backup/previous-db.sqlite3"
zstd -d /storage/backup/db/{PATH_TO_BACKUP_ZST} -o /storage/backup/restore-db.sqlite3
sqlite3 /storage/db.sqlite3 ".restore /storage/backup/restore-db.sqlite3
When all is confirmed working with the restore, you can delete
previous-db.sqlite3
and restore-db.sqlite3
.
The latest backup is available via symlink at
/storage/backup/db/latest-db.sqlite3.zst
. You can use scp
, zstd -d
and
`sqlite3 ".restore" to bring your local database into the same state as the
production database. You may also wish to retrieve the coding systems
databases, otherwise you will not be able to interact with codelists that
require them.
# macOS
brew install just
# Linux
# Install from https://github.com/casey/just/releases
# Add completion for your shell. E.g. for bash:
source <(just --completions bash)
# Show all available commands
just # shortcut for just --list
See https://github.com/Schniz/fnm#installation.
The development server can be run locally, as described below, or in docker.
To use Django Debug Toolbar in development, set DJANGO_DEBUG_TOOLBAR
.
It is not enabled by default because it adds tens of seconds to the load time of some pages.
just dev-setup
just run
Access at http://localhost:7000
# python tests and coverage
just test-py
# run specific test with usual pytest syntax
just test-py <path/to/test>::<test name>
# js tests
just assets-test
# all tests
just test
# check python files (black, isort, flake8)
just check
# fix black and isort
just fix
# js linting
just assets-lint
Run a local development server in docker:
just docker-serve
Run the python tests in docker
just docker-test-py
To run named test(s) or pass additional args, pass paths and args as you normally would to pytest:
just docker-test-py tests/reports/test_models.py::test_report_model_validation -k some-mark --pdb
Run the JS tests in docker
just docker-test-js
Run a command in the dev docker container
just docker-run <command>
Build and run a prod container locally (for testing/QA)
just docker-build prod
docker run -it --entrypoint /bin/bash opencodelists
Currently OpenCodelists handles multiple coding system releases, however it can't always handle new versions of codelists when the coding system has changed significantly since the original version was created. When a user creates a new version of a codelist, the searches from the original codelist are re-run. If these searches bring back any new codes, the version will fail to be created. Users will see a message prompting them to contact tech-support:
Codes with unknown status found when creating new version; this is likely due to an update in
the coding system. Please contact tech-support for assistance.
The codelist version can be manually created by running the following command on dokku3:
dokku$ dokku run opencodelists \
python manage.py create_and_update_draft <original version hash> --author <username>
The command will create a new draft version, and will assign statuses to each unknown code where
possible. i.e. if a new code has an ancestor code that is included, it will be implicitly
included ((+)
status), and if it has an ancestor code that is excluded, it will be implictly
excluded ((-)
status). The command will output a list of codes that were returned as "unknown"
(?
) status from the re-run searches, and have been assigned an assumed status. These should be passed on to the user to confirm.
However, on rare occasions, users may request deletion of published codelists or their versions.
Note that users can delete unpublished versions of codelists, or entirely unpublished codelists themselves. Users cannot delete published versions of codelists.
These requests should be limited to user-owned codelists, not organisation codelists.
First, visit the codelist URL of interest and note down the version ID hash on the page.
On dokku3:
- Start
shell_plus
which loads the database models for you:$ dokku run opencodelists python manage.py shell_plus
- Access the specific version of the codelist:
>>> version = CodelistVersion.objects.get_by_hash("<hash>")
- Delete the codelist version:
>>> version.delete()
First, visit the codelist URL of interest and note down the version hash on the page.
On dokku3:
- Start
shell_plus
which loads the database models for you:$ dokku run opencodelists python manage.py shell_plus
- Access the codelist through the specified version:
>>> version = CodelistVersion.objects.get_by_hash("<hash>") >>> codelist = version.codelist
- Delete the codelist and all of its versions:
>>> codelist.delete()
See codelists/scripts/README.md
See the relevant README in each of the subdirectories inside mappings/.