Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load dashboard on environment setup #112

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# custom file created at docker/superset
docker-init.sh

# Docker volumes
volumes/

Expand Down
14 changes: 7 additions & 7 deletions dashboard_viewer/dashboard_viewer/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,32 @@ class AchillesRouter:
achilles database. The rest will be stored on the default database
"""

achilles_app = "uploader"
achilles_apps = ["uploader", "materialized_queries_manager"]
achilles_db = "achilles"

def db_for_read(self, model, **_):
if model._meta.app_label == self.achilles_app:
if model._meta.app_label in self.achilles_apps:
return self.achilles_db
return None

def db_for_write(self, model, **_):
if model._meta.app_label == self.achilles_app:
if model._meta.app_label in self.achilles_apps:
return self.achilles_db
return None

def allow_relation(self, obj1, obj2, **_):
if (
obj1._meta.app_label == self.achilles_app
or obj2._meta.app_label == self.achilles_app
obj1._meta.app_label in self.achilles_apps
or obj2._meta.app_label in self.achilles_apps
):
return True
return None

def allow_migrate(self, db, app_label, **_):
if db == self.achilles_db:
result = app_label == self.achilles_app
result = app_label in self.achilles_apps
return result
if app_label == self.achilles_app:
if app_label in self.achilles_apps:
result = db == self.achilles_db
return result
return None
15 changes: 12 additions & 3 deletions dashboard_viewer/docker-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@ wait-for-it "$POSTGRES_ACHILLES_HOST:$POSTGRES_ACHILLES_PORT"

# Apply django migrations
python manage.py migrate
python manage.py migrate --database=achilles uploader
python manage.py migrate --database=achilles materialized_queries_manager
python manage.py populate_countries
python manage.py migrate --database=achilles
aspedrosa marked this conversation as resolved.
Show resolved Hide resolved

# Load initial data
if [ $SUPERSET_URL == "" ] ; then
1>&2 echo "Environment variable SUPERSET_URL not set"
exit 1
fi

sed -i s/"{SUPERSET_URL}"/$SUPERSET_URL/ /app/dashboard_viewer/tabsManager/fixtures/initial_data.json
python manage.py loaddata --app tabsManager initial_data
python manage.py loaddata --app uploader --database achilles country_initial_data
python manage.py loaddata --app materialized_queries_manager --database achilles initial_data

# Create an user for the admin app
python manage.py createsuperuser

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from contextlib import closing

from django.conf import settings
from django.core.management.base import BaseCommand
from django.db import connections
from django.db.utils import ProgrammingError
from materialized_queries_manager.models import MaterializedQuery


class Command(BaseCommand):

help = (
"Generates the materialized queries records as materialized views on Postgres"
)

def handle(self, *_, **__):
with closing(connections["achilles"].cursor()) as cursor:
for materialized_query in MaterializedQuery.objects.all():

cursor.execute(
"SELECT COUNT(*) FROM pg_matviews WHERE matviewname = %s",
[materialized_query.name],
)
if cursor.fetchone()[0] > 0:
self.stdout.write(
f"Materialized view {materialized_query.name} already exists. Skipping.",
self.style.WARNING,
)
continue

try:
cursor.execute(
f"CREATE MATERIALIZED VIEW {materialized_query.name} AS {materialized_query.query}"
)

cursor.execute(
f"GRANT SELECT ON {materialized_query.name} TO {settings.POSTGRES_SUPERSET_USER}"
)
except ProgrammingError as e:
self.stderr.write(
f"Invalid sql on query '{materialized_query.name}'. Skipping. You should edit the sql query "
f"under the admin app and the materialized views will be created. Error: {e}",
self.style.ERROR,
)
11 changes: 10 additions & 1 deletion dashboard_viewer/materialized_queries_manager/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,16 @@ def full_clean(self, exclude=None, validate_unique=True):
with closing(connections["achilles"].cursor()) as cursor:
if self.id:
old = MaterializedQuery.objects.get(id=self.id)
if old.name != self.name and old.query == self.query:

cursor.execute(
"SELECT COUNT(*) FROM pg_matviews WHERE matviewname = %s",
[old.name],
)
old_exists = cursor.fetchone()[0] > 0

if not old_exists:
self._create_materialized_view(cursor)
elif old.name != self.name and old.query == self.query:
cursor.execute(
f"ALTER MATERIALIZED VIEW {old.name} RENAME TO {self.name}"
)
Expand Down
161 changes: 161 additions & 0 deletions dashboard_viewer/tabsManager/fixtures/initial_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
[
{
"model": "tabsManager.button",
"pk": 1,
"fields": {
"title": "Death",
"icon": "times",
"position": 15,
"visible": true
}
},
{
"model": "tabsManager.button",
"pk": 2,
"fields": {
"title": "Person",
"icon": "users",
"position": 5,
"visible": true
}
},
{
"model": "tabsManager.button",
"pk": 3,
"fields": {
"title": "Visit",
"icon": "calendar-day",
"position": 12,
"visible": true
}
},
{
"model": "tabsManager.button",
"pk": 4,
"fields": {
"title": "General Concepts",
"icon": "asterisk",
"position": 16,
"visible": true
}
},
{
"model": "tabsManager.button",
"pk": 5,
"fields": {
"title": "Data Domains",
"icon": "table",
"position": 19,
"visible": true
}
},
{
"model": "tabsManager.button",
"pk": 6,
"fields": {
"title": "General",
"icon": "asterisk",
"position": 1,
"visible": true
}
},
{
"model": "tabsManager.button",
"pk": 7,
"fields": {
"title": "Population characteristics",
"icon": "globe-europe",
"position": 6,
"visible": true
}
},
{
"model": "tabsManager.button",
"pk": 8,
"fields": {
"title": "Concepts",
"icon": "book-medical",
"position": 16,
"visible": true
}
},
{
"model": "tabsManager.button",
"pk": 9,
"fields": {
"title": "Concept Domains",
"icon": "chart-bar",
"position": 17,
"visible": true
}
},
{
"model": "tabsManager.tabgroup",
"pk": 1,
"fields": {}
},
{
"model": "tabsManager.tab",
"pk": 1,
"fields": {
"url": "https://{SUPERSET_URL}/superset/dashboard/death/?standalone=true",
"group": null
}
},
{
"model": "tabsManager.tab",
"pk": 2,
"fields": {
"url": "https://{SUPERSET_URL}/superset/dashboard/person/?standalone=true",
"group": null
}
},
{
"model": "tabsManager.tab",
"pk": 3,
"fields": {
"url": "https://{SUPERSET_URL}/superset/dashboard/visit/?standalone=true",
"group": null
}
},
{
"model": "tabsManager.tab",
"pk": 4,
"fields": {
"url": "https://{SUPERSET_URL}/superset/dashboard/concepts-general/?standalone=true",
"group": 1
}
},
{
"model": "tabsManager.tab",
"pk": 5,
"fields": {
"url": "https://{SUPERSET_URL}/superset/dashboard/data-domains/?standalone=true",
"group": null
}
},
{
"model": "tabsManager.tab",
"pk": 6,
"fields": {
"url": "https://{SUPERSET_URL}/superset/dashboard/general/?standalone=true",
"group": null
}
},
{
"model": "tabsManager.tab",
"pk": 7,
"fields": {
"url": "https://{SUPERSET_URL}/superset/dashboard/period/?standalone=true",
"group": null
}
},
{
"model": "tabsManager.tab",
"pk": 8,
"fields": {
"url": "https://{SUPERSET_URL}/superset/dashboard/concepts-domains/?standalone=true",
"group": 1
}
}
]
Loading