Django 5.2 + Wagtail 7.3 + Celery app that ingests SciELO access logs, validates them, and exports COUNTER-5 metrics to OpenSearch with monthly indices and daily nested metrics.
All commands run inside Docker via the local.yml compose file unless noted.
make build # build images
make up # start all services (django, postgres, redis, celery worker+beat, mailhog)
make django_shell # Django shell via docker compose
make django_test # run full test suite (pytest)
make django_fast # tests with --failfast
make django_migrate # apply migrations
make django_makemigrations # generate new migrations
make django_createsuperuser # create Wagtail admin userRun a single test file/path:
docker compose -f local.yml run --rm django pytest path/to/test_file.pyWithout Docker (rare): use start-dev.sh after adjusting the ethernet interface name.
- Wagtail admin:
http://localhost:8009/admin(NOT Django admin at/django-admin/) - Django apps (top-level dirs):
core(Wagtail pages, users, utilities, collectors),collection,log_manager,log_manager_config,metrics,document,reports,resources,source,tracker,core_settings core/contains utilities, shared models, Wagtail hooks, templates, and thecollectors/subpackage.config/is the Django project package (settings, urls, celery_app, wsgi).- Celery pipeline:
task_daily_log_ingestion_pipeline(auto-scheduled) chains Search -> Validate -> Parse -> Export using Celery chords. Individual steps can be triggered manually via Wagtail admin. - Task names use translatable strings, e.g.
_[Log Pipeline] 1. Search Logs (Manual)— do not rename these casually, it breaks the schedule.
DJANGO_SETTINGS_MODULEdefaults toconfig.settings.local- Tests use
config.settings.test(set viapytest.ini--ds=config.settings.test) - Env files live in
.envs/.local/(local) and.envs/.production/(production) config/settings/test.pyis minimal — it extendsbase.pyand does NOT load local.py. If a test needs a setting that only exists in local.py, it must be added to test.py or set in the test directly.
- Framework: pytest (not Django's
TestCaserunner), with--reuse-dbby default - Config:
pytest.inisets--ds=config.settings.test --reuse-db - Both
unittest.TestCase(Django-style) and pytest-style tests coexist;pytestis the runner - CI runs:
build -> makemigrations -> migrate -> pytest - Shared fixtures in
core/conftest.py(autousemedia_storage,userfixture via factory-boy)
- black (line length 120 implied by flake8 config; black defaults to 88 — pre-commit config pins it)
- isort (black profile via
line_length=88) - flake8 (max-line-length=120 via setup.cfg)
- Pre-commit runs all three on commit. Configuration in
setup.cfg(flake8, isort, mypy) and.pre-commit-config.yaml.
- Two SciELO libs (
scielo_log_validator,scielo_usage_counter) are installed from local repos mounted at/app/scielo_log_validatorand/app/scielo_usage_counterwhenUSE_LOCAL_SCIELO_LIBS=1. The local Dockerfile strips these frombase.txtduring build and installs them from the mounted volumes via the entrypoint script. - Log files volume:
/mnt/pidata2/pi/scl/logs:/app/logs(host-specific, may not exist on all machines) - Mailhog UI at
http://localhost:8029 manage.pyappendscore/tosys.pathsofrom core.utils import ...andfrom utils import ...both resolve.
- Client configured via
OPENSEARCH_URL,OPENSEARCH_BASIC_AUTH,OPENSEARCH_VERIFY_CERTS - Index naming:
usage_monthly_{collection}_{year}(e.g.usage_monthly_books_2026) - Upserts use Painless scripts for idempotent daily metric merging
OPENSEARCH_INDEX_NAME(defaultusage) andOPENSEARCH_API_KEYare defined in base settings but not widely used
- When you need to search framework/library docs (Django, Wagtail, Celery, OpenSearch, etc.), use
context7tools. - When you need to find code examples or patterns from open-source projects, use
gh_greptools.
- Multi-language:
pt-br(default),en,es - Wagtail URL prefixes disabled (
prefix_default_language=False) - After adding a language, run
make wagtail_syncandmake wagtail_update_translation_field wagtail-modeladminis used for managing pipeline entities in admin