Create a GeoNode project

The geonode-project repository contains a Django project template that allows us to create a brand new web project that has GeoNode core as a dependency.

In simple words, using this project template, can customize our GeoNode instance without actually touching the core GeoNode code.

Thanks to the power of Django, we can override HTML templates, views, and, within certain limits, the models.

We’ll be calling a GeoNode project (or geonode-project instance) which is a Django project created using the geonode-project template.

In this section we will learn how to:

  • Create a new virtual environment for our geonode-project instance

  • Initialize a new geonode project called my_geonode

  • Modify the look-and-feel of the my_geonode project

Create my_geonode Django project

First of all, we need to create a new virtualenv based on Python 3.10:

mkvirtualenv -p $(which python3.10) my_geonode
command output
created virtual environment CPython3.8.10.final.0-64 in 385ms
  creator CPython3Posix(dest=/home/geonode-vm-321/.virtualenvs/my_geonode, clear=False, global=False)
  seeder FromAppData(download=False, pip=latest, setuptools=latest, wheel=latest, pkg_resources=latest, via=copy, app_data_dir=/home/geonode-vm-321/.local/share/virtualenv/seed-app-data/v1.0.1.debian.1)
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
virtualenvwrapper.user_scripts creating /home/geonode-vm-321/.virtualenvs/my_geonode/bin/predeactivate
virtualenvwrapper.user_scripts creating /home/geonode-vm-321/.virtualenvs/my_geonode/bin/postdeactivate
virtualenvwrapper.user_scripts creating /home/geonode-vm-321/.virtualenvs/my_geonode/bin/preactivate
virtualenvwrapper.user_scripts creating /home/geonode-vm-321/.virtualenvs/my_geonode/bin/postactivate
virtualenvwrapper.user_scripts creating /home/geonode-vm-321/.virtualenvs/my_geonode/bin/get_env_details
(my_geonode) geonode-vm-321@geonodevm-3:~$

Install the correct version of Django

pip install Django==3.2.18
command output
Collecting Django==3.2.18
  Downloading Django-3.2.15-py3-none-any.whl (7.9 MB)
     |████████████████████████████████| 7.9 MB 6.5 MB/s 
Collecting pytz
  Downloading pytz-2021.3-py2.py3-none-any.whl (503 kB)
     |████████████████████████████████| 503 kB 6.3 MB/s 
Collecting sqlparse>=0.2.2
  Downloading sqlparse-0.4.2-py3-none-any.whl (42 kB)
     |████████████████████████████████| 42 kB 1.2 MB/s 
Collecting asgiref<4,>=3.3.2
  Downloading asgiref-3.5.0-py3-none-any.whl (22 kB)
Installing collected packages: pytz, sqlparse, asgiref, Django
Successfully installed Django-3.2.15 asgiref-3.5.0 pytz-2021.3 sqlparse-0.4.2

The new VirtualEnv called my_geonode is now ready to be used.

Let’s create the target folder with the right permissions for the geonode project:

cd /opt
sudo mkdir geonode-project
sudo chown -Rf $USER: geonode-project/
cd geonode-project/

Now clone the geonode-project template from the repository:

git clone https://github.com/GeoNode/geonode-project.git -b 4.1.x

Create the my_django project by using the geonode-project as a template:

django-admin startproject --template=./geonode-project -e py,sh,md,rst,json,yml,ini,env,sample,properties -n monitoring-cron -n Dockerfile my_geonode

The previous command line should create a new folder called my_geonode that contains a Django project instance

Content of "my_geonode/src" directory
/opt/geonode-project/my_geonode/src$ ll
total 152
drwxrwxr-x 6 geonode-vm-321 geonode-vm-321  4096 Mar 16 17:42 ./
drwxrwxr-x 4 geonode-vm-321 geonode-vm-321  4096 Mar 16 17:42 ../
-rwxrwxr-x 1 geonode-vm-321 geonode-vm-321  1280 Mar 16 17:42 celery-cmd*
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321   540 Mar 16 17:42 celery.sh
-rwxrwxr-x 1 geonode-vm-321 geonode-vm-321  2578 Mar 16 17:42 entrypoint.sh*
drwxrwxr-x 2 geonode-vm-321 geonode-vm-321  4096 Mar 16 17:42 fixtures/
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321   506 Mar 16 17:42 jetty-runner.xml
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321   559 Mar 16 17:42 Makefile
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321    52 Mar 16 17:42 manage_dev.sh.sample
-rwxrwxr-x 1 geonode-vm-321 geonode-vm-321  1092 Mar 16 17:42 manage.py*
-rwxrwxr-x 1 geonode-vm-321 geonode-vm-321    77 Mar 16 17:42 manage.sh*
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321   256 Mar 16 17:42 monitoring-cron
drwxrwxr-x 5 geonode-vm-321 geonode-vm-321  4096 Mar 16 17:42 my_geonode/           <------- Django main app folder
drwxrwxr-x 3 geonode-vm-321 geonode-vm-321  4096 Mar 16 17:42 package/
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321 39745 Mar 16 17:42 pavement.py
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321    40 Mar 16 17:42 paver_dev.sh.sample
-rwxrwxr-x 1 geonode-vm-321 geonode-vm-321    31 Mar 16 17:42 paver.sh*
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321    13 Mar 16 17:42 README.md
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321   160 Mar 16 17:42 requirements.txt      <------- GeoNode/Django dependencies
drwxrwxr-x 3 geonode-vm-321 geonode-vm-321  4096 Mar 16 17:42 scripts/
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321  1642 Mar 16 17:42 setup.py
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321 22868 Mar 16 17:42 tasks.py
-rw-rw-r-- 1 geonode-vm-321 geonode-vm-321  2447 Mar 16 17:42 uwsgi.ini
-rwxrwxr-x 1 geonode-vm-321 geonode-vm-321   691 Mar 16 17:42 wait-for-databases.sh*

By taking a look into the /opt/geonode-project/my_geonode/src/my_geonode you should be able to recognize a standard Django app structure

drwxrwxr-x 5 geonode geonode 4096 Sep  9 15:43 ./
drwxrwxr-x 7 geonode geonode 4096 Sep  9 15:43 ../
-rw-rw-r-- 1 geonode geonode 1279 Sep  9 15:43 apps.py
drwxrwxr-x 2 geonode geonode 4096 Sep  9 15:43 br/
-rw-rw-r-- 1 geonode geonode 1356 Sep  9 15:43 celeryapp.py
-rw-rw-r-- 1 geonode geonode 1042 Sep  9 15:43 __init__.py
-rw-rw-r-- 1 geonode geonode 5000 Sep  9 15:43 settings.py   <------- Django settings
drwxrwxr-x 6 geonode geonode 4096 Sep  9 15:43 static/
drwxrwxr-x 2 geonode geonode 4096 Sep  9 15:43 templates/    <------- HTML templates
-rw-rw-r-- 1 geonode geonode 1234 Sep  9 15:43 urls.py       <------- main URL patterns
-rw-rw-r-- 1 geonode geonode 1779 Sep  9 15:43 version.py
-rw-rw-r-- 1 geonode geonode 1980 Sep  9 15:43 wsgi.py

Some files are still missing (like the views, models, and migrations) since they are not needed by default.

Install dependencies

We need to install the GeoNode project dependencies first.

The default requirements.txt file contains two dependencies, which are

  • core GeoNode

  • geonode_mapstore_client: the adapter for using mapstore in GeoNode

Performing a pip install -r requirements.txt would install these sources inside the virtual environment hidden directory, but we need our copy of the sources to be installed (remember, we need a setup for developers!)

Edit the file /opt/geonode-project/my_geonode/src/requirements.txt and comment out the line

cd /opt/geonode-project/my_geonode/src
vim requirements.txt
--- requirements.txt	2022-07-25 12:40:54.883782750 +0100
+++ requirements.txt	2022-07-25 13:15:59.807862863 +0100
@@ -1,2 +1,3 @@
-# -e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.1.x#egg=django_geonode_mapstore_client
+-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.1.x#egg=django_geonode_mapstore_client
+#GeoNode==4.0.3
+-e /opt/geonode

Then install the other listed requirements:

workon my_geonode
pip install -r /opt/geonode-project/my_geonode/src/requirements.txt

This will install the local GeoNode and a copy of the geonode-mapstore-client in development mode

As part of the GeoNode setup, you need to manually install some requirements that are bound to the locally installed binary packages:

pip install pygdal=="`gdal-config --version`.*"

Finally, install the current app in dev mode

cd /opt/geonode-project/my_geonode/src/
pip install -e .
# Ensure the NGINX and UWSGI services have been stopped
sudo systemctl stop nginx
sudo pkill -9 -f uwsgi
sudo ps aux | grep uwsgi
  • Let’s edit the project .env in order to match the dev environment

Configuration

The GeoNode settings are configurable using environment variables. There is a sample file containing the most common variables that may need to be customized.

Copy that sample file into the file we are going to edit:

# Ensure we are in the correct virtualenv and folder
workon my_geonode
cd /opt/geonode-project/my_geonode/src
cp ../.override_dev_env.sample ../.override_dev_env

Also, copy the sample files used to run the admin commands:

cd /opt/geonode-project/my_geonode/src/
cp paver_dev.sh.sample paver_dev.sh
cp manage_dev.sh.sample manage_dev.sh
cp ../dev_config.yml .

chmod +x paver_dev.sh manage_dev.sh

Edit the .override_dev_env file

cd /opt/geonode-project/my_geonode/src
vim ../.override_dev_env

Make sure the database info is correct and add the following line

export ASYNC_SIGNALS=False

This is a recap of the edited lines:

(my_geonode) geonode@geonode-32x-vm:/opt/geonode-project/my_geonode$ diff -u --color .override_dev_env.sample src/.override_dev_env
--- ../.override_dev_env.sample	2022-03-17 16:37:38.211554417 +0000
+++ ../.override_dev_env 2022-03-17 17:03:35.357738873 +0000
@@ -7,13 +7,13 @@
 
 export GEONODE_INSTANCE_NAME=geonode
 export DJANGO_SETTINGS_MODULE=my_geonode.settings
-export GEONODE_DATABASE=my_geonode
+export GEONODE_DATABASE=geonode
 export GEONODE_DATABASE_PASSWORD=geonode
-export GEONODE_GEODATABASE=my_geonode_data
+export GEONODE_GEODATABASE=geonode_data
 export GEONODE_GEODATABASE_PASSWORD=geonode
 
-export DATABASE_URL=postgis://my_geonode:geonode@localhost:5432/my_geonode
-export GEODATABASE_URL=postgis://my_geonode_data:geonode@localhost:5432/my_geonode_data
+export DATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode
+export GEODATABASE_URL=postgis://geonode:geonode@localhost:5432/geonode_data
 export DEFAULT_BACKEND_DATASTORE=datastore
 
 export GEOSERVER_WEB_UI_LOCATION=http://localhost:8080/geoserver/
@@ -94,3 +94,5 @@
 export EXIF_ENABLED=True
 export CREATE_LAYER=True
 export FAVORITE_ENABLED=True
+
+export ASYNC_SIGNALS=False

Align the DB and GeoNode

workon my_geonode
cd /opt/geonode-project/my_geonode/src

./manage_dev.sh makemigrations
./manage_dev.sh migrate

Align the internal URLs and Metadata links

# The order is important! Those are regex expressions and will be executed one after the other...

# Fix GeoServer URLs first
./manage_dev.sh migrate_baseurl --source-address=http://localhost/geoserver --target-address=http://localhost:8080/geoserver

# Fix GeoNode URLs
./manage_dev.sh migrate_baseurl --source-address=http://localhost/ --target-address=http://localhost:8000/

# Align the Metadata links
./manage_dev.sh set_all_datasets_metadata -d -p

Run GeoNode

Finally, start my_geonode with either

./manage_dev.sh runserver 0.0.0.0:8000

or (run in the background)

./paver_dev.sh start_django
  • Notice how we don’t need to fix the GeoServer OAuth2 endpoints since we already did that in the previous section

  • Open the browser and go to the location http://localhost:8000

  • The main page and theme have been changed again

image

Next Section: Customize a geonode project model