knowledge_base is a production-like Django pet project for a personal knowledge base: notes, study summaries, technical guides, bug fixes, and ideas. The scope stays intentionally tight: a clean core, clear business rules, reusable query logic, and a complete HTML + API baseline without premature complexity.
- Public and private notes with author-only editing.
- Search across title, content, and tags.
- Tags with slug generation and case-insensitive uniqueness.
- Comments with soft delete.
- Voting with update-in-place behavior.
- Favorites for authenticated users.
- HTML interface and DRF API with JWT authentication.
- Shared selectors/query helpers reused across HTML and API.
- CI with tests, lint, format check, and coverage report.
core/selectors.pyis the source of truth for visibility rules and shared note query logic.comments_countandvote_scoreare annotated at queryset level to avoid N+1 queries in lists and detail pages.vote_scoreuses aSubquery, so it is not corrupted by JOIN duplication with comments.- Tag visibility is protected: if a user cannot see any note for a tag, both HTML and API return
404. - The project keeps a single
settings.pyand avoids over-engineering in the early stage.
- Python 3.13
- Django 5.1
- Django REST Framework
- Simple JWT
- SQLite
- Pytest
- Ruff
- Celery (basic eager/dev setup for cache warmup task)
python -m venv .venv
.\.venv\Scripts\python -m pip install --upgrade pip
.\.venv\Scripts\python -m pip install -r requirements-dev.txt
.\.venv\Scripts\python manage.py migrate
.\.venv\Scripts\python manage.py createsuperuser
.\.venv\Scripts\python manage.py runserverpython -m venv .venv
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
python manage.py migrate
python manage.py createsuperuser
python manage.py runserverOpen:
http://127.0.0.1:8000/http://127.0.0.1:8000/admin/
knowledge_base/- settings, root URLs, ASGI/WSGI, Celery bootstrapaccounts/- signup/login, profile model, profile pagenotes/- note model, HTML CRUD, search, privacy rulestags/- tag model and tag pagecomments/- comments and soft delete logicvotes/- voting model and vote update logicfavorites/- favorites page and add/remove behaviorapi/- serializers, permissions, pagination, REST endpointscore/- selectors, services, constants, reusable taskstemplates/- shared and app HTML templatesdocs/screenshots/- README screenshots
GET /GET /notes/GET|POST /notes/create/GET|POST /notes/<slug>/GET|POST /notes/<slug>/edit/GET|POST /notes/<slug>/delete/GET /tags/<slug>/GET /favorites/GET /profile/<username>/GET|POST /accounts/signup/GET|POST /accounts/login/
POST /api/auth/token/POST /api/auth/token/refresh/
GET /api/notes/POST /api/notes/GET /api/notes/<slug>/PATCH /api/notes/<slug>/DELETE /api/notes/<slug>/
GET /api/notes/<slug>/comments/POST /api/notes/<slug>/comments/
POST /api/notes/<slug>/vote/
POST /api/notes/<slug>/favorite/DELETE /api/notes/<slug>/favorite/GET /api/favorites/
GET /api/tags/GET /api/tags/<slug>/notes/
Get JWT pair:
curl -X POST http://127.0.0.1:8000/api/auth/token/ \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password"}'Create a note:
curl -X POST http://127.0.0.1:8000/api/notes/ \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"title":"Django tips","content":"Use select_related.","is_public":true,"tag_names":["django","orm"]}'Vote for a note:
curl -X POST http://127.0.0.1:8000/api/notes/django-tips/vote/ \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"value":1}'Run tests:
pytest -qRun coverage:
pytest --cov=. --cov-report=term-missingRun lint:
ruff check .
ruff format --check .The project was re-checked in a fresh clone with a clean virtual environment:
- dependency installation from
requirements-dev.txt python manage.py migratepython manage.py checkpytest -qpytest --cov=. --cov-report=term-missingruff check .ruff format --check .
Current local result:
- tests:
24 passed - coverage:
92%
The project includes core.tasks.warm_public_notes_cache, a small Celery task that warms the cached first page of public notes. In development and tests, Celery runs eagerly. For a real deployment, the broker/backend should be switched from in-memory to Redis or another persistent backend.


