Source code for the ckan.org website — the CKAN project site, built with Django 5.2.17 and Wagtail 7.4.
| Resource | Link |
|---|---|
| 🌍 Live site | https://ckan.org/ |
| 📚 Documentation | https://docs.ckan.org/ |
| 💻 GitHub (CKAN repos) | https://github.com/ckan |
| ✨ Features | https://ckan.org/features |
| 🗂️ Showcase (portals) | https://ckan.org/showcase |
| 📝 Blog | https://ckan.org/blog |
| 📅 Events | https://ckan.org/events |
| ❓ FAQ | https://ckan.org/faq |
| 🛟 Support — community | https://ckan.org/community |
| 🛟 Support — commercial | https://ckan.org/commercial |
- Title:
ckan.org - Preview: https://ckan.org/
- Tech stack: Python 3.11+ · Django 5.2.17 · Wagtail 7.4
Condensed, collapsible overview of the repository layout.
📂 ckan-org/ — Django + Wagtail project root
ckan-org/
├── ckanorg/ # Django project core
│ ├── settings/base.py # main settings (DB, cache, email, Wagtail)
│ ├── static/ # global source assets (css, js, img, fonts, scss)
│ ├── templates/ # base.html, header.html, footer.html + per-app templates
│ └── urls.py · views.py · wsgi.py
│
├── Wagtail apps — each has models.py, admin.py, views.py, urls.py, tests.py,
│ migrations/ (and templatetags/ where needed):
│ ├── home/ · blog/ · events/ · stories/ · anniversary/
│ ├── portals/ · ckan_pages/ · faq/ · contact/ · managers/
│ └── menus/ · dashboard/ · search/ · streams/
│
├── scss/ # Sass sources compiled into the static output
├── static/ # collected static output (STATIC_ROOT / Whitenoise)
├── media/ # user uploads (symlink to shared storage on servers)
├── cache/ # wagtail-cache page cache (symlink on servers)
│
├── manage.py # Django management entrypoint
├── requirements.txt # Python dependencies
├── Dockerfile · deploy.sh · bitbucket-pipelines.yml
├── robots.txt · checklist.md · .gitignore
└── LICENSE.txt · README.md
ℹ️ Note:
streams/is a live Wagtail app, not a duplicate tree. It provides the shared snippet/block models used elsewhere — e.g.CkanForCard,PoweredCard,PoweringImage,GitCardBlockandPoweringOpendataBlock(referenced byhome/andckan_pages/). A previously duplicated project tree that had accumulated understreams/was removed to prevent stale-template drift.
The site runs on Python 3.11+ with the following core stack (see requirements.txt for the full list):
- Python 3.11+
- Django 5.2.17
- Wagtail 7.4
- Database: PostgreSQL 12+ (SQLite is fine for local development)
The steps below assume a fresh local clone on Linux/macOS. Production uses PostgreSQL; for local development you can use SQLite (see steps 3 and 7).
python3 -m venv wagenv
source wagenv/bin/activate
git clone https://github.com/ckan/ckan.org.git
pip install wheel
pip install -r requirements.txt
Remove the tracked cache and media links (they point to shared server storage), create the local folders, and collect the static files:
mkdir -p media static
python manage.py collectstatic
diff --git a/ckanorg/settings/base.py b/ckanorg/settings/base.py
index be311ca..ec8777f 100644
--- a/ckanorg/settings/base.py
+++ b/ckanorg/settings/base.py
@@ -225,11 +225,7 @@ with open(BASE_DIR + '/../config/secret.txt') as f:
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'NAME': 'ckanorg',
- 'USER': 'ckanorg',
- 'PASSWORD': DB_PASS,
- 'HOST': DB_HOST,
- 'PORT': 5432,
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Note: Wagtail 7.4 targets PostgreSQL 12+; SQLite is only a convenience for local development.
- Recommended: copy the shared dummy
db.sqlite3file (ask the managers) into theckan.orgfolder so you don't have to rebuild every page from scratch. - Otherwise migrate a fresh database:
python manage.py makemigrations
python manage.py migrate
💡 Helpful — avoid first-run
DoesNotExistcrashes on a fresh databaseIf you start from an empty database, the front end crashes with
Page.DoesNotExiston the very first load: the footer template tag{% add_blog_post_url %}inckanorg/templates/footer.htmlcallsPage.objects.get(slug='blog'), which requires the Wagtail page tree to already exist.To avoid this, use the shared dummy
db.sqlite3above, or, when migrating from scratch, runpython manage.py createsuperuserand create the core top-level pages (at minimum a Blog listing page with slugblog, the home page and the Wagtail site record) in the admin before openinghttp://127.0.0.1:8000/.
diff --git a/ckanorg/settings/base.py b/ckanorg/settings/base.py
index be311ca..3837822 100644
--- a/ckanorg/settings/base.py
+++ b/ckanorg/settings/base.py
@@ -49,7 +49,6 @@ INSTALLED_APPS = [
'wagtail.admin',
- 'wagtailcache',
'modelcluster',
'taggit',
@@ -87,18 +86,8 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'wagtail.contrib.redirects.middleware.RedirectMiddleware',
- 'wagtailcache.cache.FetchFromCacheMiddleware',
]
-CACHES = {
- 'default': {
- 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
- 'LOCATION': os.path.join(BASE_DIR, 'cache'),
- 'KEY_PREFIX': 'wagtailcache',
- 'TIMEOUT': 3600, # one hour (in seconds)
- }
-}
-
X_FRAME_OPTIONS = 'ALLOWALL'
ROOT_URLCONF = 'ckanorg.urls'
diff --git a/ckanorg/settings/base.py b/ckanorg/settings/base.py
index be311ca..d0b68dc 100644
--- a/ckanorg/settings/base.py
+++ b/ckanorg/settings/base.py
@@ -192,11 +181,13 @@ WAGTAIL_SITE_NAME = "ckanorg"
BASE_URL = '<https://ckan.org'>
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
-EMAIL_HOST = 'email-smtp.eu-central-1.amazonaws.com'
+EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
-DEFAULT_FROM_EMAIL = 'noreply@ckan.org'
+EMAIL_HOST_USER = 'linkdigitaltest@gmail.com'
+DEFAULT_FROM_EMAIL = 'linkdigitaltest@gmail.com'
+EMAIL_HOST_PASSWORD = 'my-password'
+
ACCOUNT_AUTHENTICATION_METHOD = 'username_email'
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
@@ -216,20 +207,11 @@ ALLOWED_HOSTS = ['*']
WAGTAIL_APPEND_SLASH = False
-with open(BASE_DIR + '/../config/secret.txt') as f:
- data = f.read().strip().split(',')
- SECRET_KEY = data[0]
- EMAIL_HOST_PASSWORD = data[1]
- DB_HOST = data[2]
- DB_PASS = data[3]
- RECAPTCHA_PUBLIC_KEY = data[4]
- RECAPTCHA_PRIVATE_KEY = data[5]
- EMAIL_HOST_USER = data[6]
+SECRET_KEY = 'my-secret-key'
🔒 Security — don't hardcode secrets in
settings/base.py
base.pyis committed to the repository, so real credentials —SECRET_KEY, email/DB passwords, reCAPTCHA keys — must never be hardcoded there. The placeholder values in the steps above are for local development only.Prefer environment variables or a git-ignored local override, e.g. add
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'dev-only-insecure-key')at the bottom ofbase.py.On servers, real secrets live in
config/secret.txt, which sits outside the repo and is never committed.
13. Open http://127.0.0.1:8000/ in your browser.
You will not see some images, as media folder is empty. If you need them, you can edit pages in admin section and upload your test images. (To login as admin into the provided sqlite database, contact managers).
python manage.py makemigrations
python manage.py migrate
python manage.py collectstatic
to work with django models and styles.
If you want to be ensured that outdated JS bundles are removed use:
python manage.py collectstatic --clear --noinput
Populate the references table and ensure that usage counts for images, documents and snippets are displayed accurately
python manage.py rebuild_references_index
Tests are written as Django TestCase classes in each app's tests.py (e.g. contact/tests.py, faq/tests.py, portals/tests.py, stories/tests.py, anniversary/tests.py).
Run the pytest suite from the project root (pytest-django picks up DJANGO_SETTINGS_MODULE from manage.py):
# Install pytest support (once)
pip install pytest pytest-django
# Run the full suite
pytest
# Run a single app / a single test case
pytest contact/ -v
pytest contact/tests.py::ParseContactFormTests -vDjango's built-in test runner also works:
python manage.py test
python manage.py test contactA quick pre-merge validation pass:
python manage.py check
python manage.py makemigrations --check --dry-run
pytest- Create a new fork from
mainbranch of the repositoryhttps://github.com/ckan/ckan.org. A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project. So all tasks that you push are going to our fork repository, not the main one. If it was done earlier be sure you have clonedmainbranch of the repository with last updates. - Create a new branch from
mainbranch of your forked repository and name it as "[task key] / [task summary]". - Make all required changes.
- Push your finished task code to your fork repository (cloned).
- Deploy your changes to Development environment by making a Pull Request to
developbranch of original repository so the PO (Product owner) can merge it after he/she will test the work done on Development.
- software
OS: Ubuntu 24.04.5 LTS (Lunar) Python: 3.12.12 - hardware
CPU: Intel® Core™ i5 GPU: Intel® Iris® Xe Graphics
Many thanks to everyone who has helped build and maintain the ckan.org website.
| GitHub | Name |
|---|---|
| Alex-Pavlyuk | Alex Pavlyuk |
| alexmorev | Aleksey Morev |
| amercader | Adrià Mercader |
| ostyhar | — |
- Website source: https://github.com/ckan/ckan.org
This material is copyright (c) 2006-2018 Open Knowledge Foundation and contributors.
It is open and licensed under the GNU Affero General Public License (AGPL) v3.0 whose full text may be found at:
