First you have to decide, wether you want to run the application via Docker or simply via python. For backend developers, I would recommend to install it regularly with python. For frontend developers it is simpler to just run docker and not to care about python environment and dependencies.
Obviously, you have to clone this repo first.
Step 1
If not present, the app data must be extracted from the eGon-data database first. The scripts in data_deployment/ creates all required geopackages, see data_deployment.md for further instructions.
Step 2
These geopackages have to be placed into folder egon/data/, so that they can be found by the application and uploaded into database. All packages are just dropped into this folder (no hierarchy).
Prerequisite: conda (Anaconda /Miniconda) Enter repo folder and set up a conda environment and activate it:
conda env create -f environment.yml
conda activate egon
Install poetry (python dependency manager used in this project) and dependencies for the project (Note: Installing poetry via pip into same environment is not recommended and can cause trouble! Instead it should be installed system-wide via command below or pipx):
curl -sSL https://install.python-poetry.org | python3 -
poetry install
The project uses pre-commit in order to check for errors and linting bugs before commits. To activate pre-commit simply run:
pre-commit install
Now you should be ready to start the application by running: (This will throw a database error, as we must set up a database)
python manage.py runserver
As the project uses a database you must have to set up a database first. I highly recommend to use postgresql for that. Please follow online tutorials to set up database correctly and come back here, if everything is set up.
Configuration is done by django configuration files in config/settings/ and by using environment variables (for database, redis, etc.). Environment variables have to be set using the following structure:
DATABASE_URL=postgis://<user>:<password>@<host>:<port>/<database>
TILING_SERVICE_STYLE_ID=<URL to mapbox style>
TILING_SERVICE_TOKEN=<token>
PROJ_LIB=<path to folder _proj/_, needed for GDAL>
REDIS_URL=redis://<host>:<port>
(if REDIS is used)USE_DISTILLED_MVTS=<True/False>
(should be set to False at first)USE_DOCKER=<True/False>
You can set up environment variables either by using your IDE, or by setting them via your system. Please follow tutorials for this or ask your local IT-expert.
- Merge given local env files into newly created root
.env
file:make local_env_file
- Adjust values in root
.env
file to your needs. For example your hostname is probablylocalhost
and notpostgres
. Maybe you want also use a different user or password. - Set environment variable DJANGO_READ_DOT_ENV_FILE to True, e.g. via simple
export:
export DJANGO_READ_DOT_ENV_FILE=True
. You can persist the env export by putting it for example into your bashrc file (terminal restart needed afterwards):echo -e "\n# Use .env file for Egon in local dev environment\nexport DJANGO_READ_DOT_ENV_FILE=True" >> ~/.bashrc
- Create in your local Postgres Database Management System a database like defined in
your
.env
file (e.g. viapgAdmin
orpsql
) - In your database create following extensions:
CREATE EXTENSION postgis; CREATE EXTENSION postgis_raster;
First you have to set up all tables in the database by runnning:
python manage.py migrate
Afterwards you have to load in data. To simplify data commands a Makefile has been
added, which can be used by command make
.
You can load all data by running (or you can run them one-by-one):
make load_regions load_data
And you can empty all data by running:
make empty_data empty_regions
Make sure you have Docker
and Docker-Compose installed.
You may have to put sudo
in front of the commands.
While using the following commands, exchange production.yml (production server) and _
local.yml_ (local development) accordingly to your needs!
docker-compose -f production.yml up -d --build
Depending on your deployment (local/production), the server should be available
under localhost:8000
(local) or
at docker container at port 5000 (production server needs to be forwarded by a proxy
server).
Sometimes the CSS is not loaded correctly in production mode, restarting the production server can help:
docker-compose -f production.yml restart
By now, no data is visible, as the geometries have to be loaded into database first by the following steps.
Following steps are necessary to refresh/load data on production server:
docker-compose -f production.yml run --rm django python manage.py migrate
docker-compose -f production.yml run --rm django make empty_data empty_regions
docker-compose -f production.yml run --rm django make load_regions load_data
In order to increase loading speed of vector tiles, the tiles can be pre-rendered. This is done by using distilled vector tiles. You can create those vector tiles by using the following commands: (Note: You have to recreate distilled vector tiles after each data update in order to see changes on the map)
docker-compose -f production.yml run --name egon_distill -e DISTILL=True django /bin/bash -c "python manage.py collectstatic --noinput; python manage.py distill-local --force --exclude-staticfiles ./distill"
docker cp egon_distill:/app/distill/ ./egon/static/mvts/
# commit and push, afterwards remove temp container:
docker rm -f egon_distill
In order to add new layers to the application following steps must be made:
-
add geopackages containing vector layer data into folder egon/data.
-
create a Django model in
egon/map/models.py
with following minimum requirements:- it must contain a
GeometryField
(Point/Polygon) namedgeom
, - it must contain the default Django
Manager
as attributeobjects
, - it must contain a
MVTManager
derived fromegon/map/managers.py
. Normally, aStaticMVTManager
(which activates filtering of vector tiles by given zoom level) should be chosen.
- it must contain a
-
run
makemigrations
andmigrate
(see commands above), -
add an entry for new layer in
MODELS
inegon/utils/data_processing.py
, -
load layer data into DB by running
load_data
or by loading only specific data.
Now the layer data is present in DB, but not yet served as vector tiles. This can be accomplished with following steps:
- add mapbox layer information in
egon/map/layers.py
(either in existing category or by adding a new one) - add layer to
STATIC_MVT_LAYERS
inegon/map/mvt_layers
.
The layer and a related switch should now be visible on map and on the detail panel.
We encourage all to build application tests. As best practice, this should be done immediately after documentation of the application being built, before starting on any coding.
This project uses the Pytest, a framework for easily building simple and scalable tests. After you have set up to develop locally, run the following commands to make sure the testing environment is ready:
pytest
You will get a readout of the users app that has already been set up with tests. If you do not want to run the pytest on the entire project, you can target a particular app by typing in its location:
pytest <path-to-app-in-project/app>
If you set up your project to develop locally with docker, run the following command:
docker-compose -f local.yml run --rm django pytest
Targeting particular apps for testing in docker follows a similar pattern as previously shown above.
You should build your tests to provide the highest level of code coverage. You can run the pytest with code coverage by typing in the following command:
coverage run -m pytest
Once the tests are complete, in order to see the code coverage, run the following command:
coverage report
If you're running the project locally with Docker, use these commands instead:
docker-compose -f local.yml run --rm django coverage run -m pytest
docker-compose -f local.yml run --rm django coverage report
Note
At the root of the project folder, you will find the pytest.ini file. You can use this to customize the pytest to your liking.
There is also the .coveragerc. This is the configuration file for the coverage tool.
Example to only load specific data:
docker-compose -f production.yml run --rm django python -u manage.py shell --command="from djagora.utils import load_overlays; from djagora.utils.load_configs import DYNAMIC_OVERLAYS; overlays = [item for item in DYNAMIC_OVERLAYS if item['name'].startswith('settlement')]; load_overlays.run(overlays=overlays)"
GDAL ^^^^
Attention: First, check if environment variable PROJ_LIB
points to correct proj directory.
This can lead to several strange (and non-helpful) errors!