Repository: wsvincent/awesome-django
Branch: main
Commit: 3b894153dfe4
Files: 23
Total size: 92.8 KB
Directory structure:
gitextract_k_rsco0f/
├── .editorconfig
├── .github/
│ ├── CODEOWNERS
│ ├── issue_template.md
│ ├── pull_request_template.md
│ └── workflows/
│ ├── lint.yml.disabled
│ └── stale.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .vscode/
│ └── launch.json
├── 404.html
├── CNAME
├── Gemfile
├── LICENSE
├── README.md
├── _config.yml
├── _includes/
│ └── head_custom.html
├── _sass/
│ └── color_schemes/
│ └── django.scss
├── compose.yml
├── contributing.md
├── justfile
├── modd.conf
├── pyproject.toml
└── scripts/
└── main.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{py,rst,ini}]
indent_size = 4
indent_style = space
[*.py]
line_length=120
multi_line_output=3
[*.{css,html,js,json,sass,scss,yml,yaml}]
indent_size = 2
indent_style = space
[*.md]
indent_size = 4
indent_style = space
trim_trailing_whitespace = false
[justfile]
indent_size = 4
indent_style = space
[{Makefile,modd.conf}]
indent_style = tab
================================================
FILE: .github/CODEOWNERS
================================================
* @wsvincent @jefftriplett
================================================
FILE: .github/issue_template.md
================================================
---
name: ⛔️ Add a New Project [Please Submit as Pull Request]
about: How to submit a new Django project for the Awesome Django list
title: ''
labels:
assignees: ''
---
# ⚠️ Please Do Not Create an Issue to Submit Projects
We've moved to a pull request-based submission process to manage contributions to the Awesome Django list better.
## How to Submit Your Project
1. Fork the repository
2. Add your project to the appropriate category in `README.md`
3. Submit a pull request and fill in our pull request template:
## Submission Criteria
To maintain the quality of our list, please ensure your project meets these criteria:
- Has been maintained for a reasonable period
- Provides clear documentation
- Solves a specific problem or adds value to the Django ecosystem
- Is actively maintained
- Has a stable release history (for packages)
## Need Help?
If you need assistance with the submission process:
1. Check our contribution guidelines in the repository
2. Review existing pull requests for examples
3. Open a discussion if you have questions about the process
*This issue will be automatically closed. Please submit your project via pull request.*
================================================
FILE: .github/pull_request_template.md
================================================
---
name: Add a new project
about: Suggest a new Django project for the Awesome Django list
title: "[NEW] Project Name"
---
> **⚠️ REQUIRED: This template MUST be filled out completely.**
>
> Pull requests that delete this template, leave sections blank, or ignore the requirements **will be closed without review**. We will not chase you for missing information—please take the time to fill out all sections before submitting.
## Project Information
1. **Project Name:**
2. **Project URL:**
3. **Description:**
_(Please provide a brief description of the project.)_
----
## Criteria
Please answer the following questions about the project you are submitting. This will help us determine whether it should be included in the Awesome Django list.
**Note:** If your project is only a few months old or has under 50 to 100 stars on GitHub, it may NOT meet the criteria for inclusion in the Awesome Django list. We recommend that you promote your project more and then consider submitting it when it has gained more visibility and community support.
**Additionally:** 🙅 We are not interested in Django Starter Kit projects, boilerplates, config templates, or similar scaffolding repos. We might change our minds, but for now, these tend to be more similar than different. Every Django Starter Kit is awesome.
**Read the Room:** 👀 Before submitting, please take time to browse through the existing projects in the list. Get a sense of the quality, maturity, and types of projects we include. If your submission is primarily promotional or doesn't clearly benefit the broader Django community, it's probably not a good fit. We're looking for projects that solve real problems and have demonstrated value to the ecosystem.
👉 Please **read** and fill out **all five questions**. We reserve the right to close your pull request without feedback if you skip one or all of them.
1. **Is the project new?**
- [ ] Yes
- [ ] No
2. **How long has the project been maintained?**
_(It doesn't have to be exact, but we generally expect at least 6 months of active maintenance history with a pattern of sustained development — not just initial creation. Please provide an approximate duration in months or years.)_
3. **How many releases has it had if it's a library or package?**
_(Please provide the number of releases, or link to the project's release history.)_
4. **Are you the author, or are you submitting the project on behalf of a company?**
- [ ] I am the author
- [ ] I am submitting on behalf of a company
- [ ] Other (please specify)
5. **What makes it awesome?**
_(Please provide a brief explanation of why you believe this project is a valuable addition to the Awesome Django list.)_
----
## AI Disclosure
We love transparent contributions. Using AI is perfectly fine, just let us know.
- [ ] Yes, this pull request was generated or assisted by AI.
- [ ] No, this pull request was authored entirely by a human.
----
## Additional Information
Please provide any additional information you believe is relevant to the project or its evaluation for inclusion in the Awesome Django list. This might include information about the project's documentation, test coverage, community support, or any unique features that set it apart from other Django projects.
_(Please provide any relevant additional information here.)_
Thank you for your submission!
================================================
FILE: .github/workflows/lint.yml.disabled
================================================
name: Lint Awesome List
on:
pull_request:
push:
branches:
- main
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: max/awesome-lint@v2.0.0
================================================
FILE: .github/workflows/stale.yml
================================================
name: Mark stale issues and pull requests
on:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 14 days'
stale-pr-message: 'This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 14 days'
stale-issue-label: 'no-issue-activity'
stale-pr-label: 'no-pr-activity'
days-before-stale: 90
days-before-close: 14
================================================
FILE: .gitignore
================================================
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/
# Used by dotenv library to load environment variables.
# .env
# Ignore Byebug command history file.
.byebug_history
## Specific to RubyMotion:
.dat*
.repl_history
build/
*.bridgesupport
build-iPhoneOS/
build-iPhoneSimulator/
## Specific to RubyMotion (use of CocoaPods):
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# vendor/Pods/
## Documentation cache and generated files:
/.yardoc/
/_yardoc/
/doc/
/rdoc/
## Environment normalization:
/.bundle/
/vendor/bundle
/lib/bundler/man/
# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
Gemfile.lock
# .ruby-version
# .ruby-gemset
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
# .rubocop-https?--*
.cache
.jekyll-cache/
.jekyll-metadata
.sass-cache/
.vendor/
_site/
assets/development.css
build
dist
docker-compose.override.yml
node_modules
package-lock.json
site
vendor
================================================
FILE: .pre-commit-config.yaml
================================================
default_language_version:
python: python3.12
exclude: |
(?x)^(
.devcontainer/devcontainer.json|
.github/contributors.json|
.vscode/launch.json|
CONTRIBUTORS.md|
frontend/.*|
static/.*
)$
repos:
- repo: https://github.com/pre-commit-ci/pre-commit-ci-config
rev: v1.6.1
hooks:
- id: check-pre-commit-ci-config
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-json
- id: check-merge-conflict
- id: check-symlinks
- id: check-toml
- id: end-of-file-fixer
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- repo: https://github.com/rtts/djhtml
rev: '3.0.6'
hooks:
- id: djhtml
entry: djhtml --tabwidth 2
alias: autoformat
- id: djcss
alias: autoformat
- id: djjs
alias: autoformat
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
- repo: https://github.com/asottile/reorder-python-imports
rev: v3.14.0
hooks:
- id: reorder-python-imports
- repo: https://github.com/asottile/pyupgrade
rev: v3.18.0
hooks:
- id: pyupgrade
alias: autoformat
args: [--py312-plus]
# - repo: local
# hooks:
# - id: rustywind
# name: rustywind Tailwind CSS class linter
# language: node
# additional_dependencies:
# - rustywind@latest
# entry: rustywind
# args: [--write]
# types_or: [html]
# # exclude: '.*\.min\.css'
================================================
FILE: .vscode/launch.json
================================================
{
"version": "0.2.0",
"configurations": [
{
"name": "Serve Jekyll Site",
"type": "shell",
"request": "launch",
"command": "bundle exec jekyll serve --livereload",
"cwd": "${workspaceFolder}",
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
}
]
}
================================================
FILE: 404.html
================================================
---
layout: default
---
404
Page not found :(
The requested page could not be found.
================================================
FILE: CNAME
================================================
awesomedjango.org
================================================
FILE: Gemfile
================================================
source "https://rubygems.org"
gem "webrick"
gem "github-pages", group: :jekyll_plugins
================================================
FILE: LICENSE
================================================
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
================================================
FILE: README.md
================================================
# Awesome Django [](https://github.com/sindresorhus/awesome)
> A curated list of awesome things related to Django. Maintained by [Will Vincent](https://github.com/wsvincent) and [Jeff Triplett](https://github.com/jefftriplett).
Please consider supporting Django by making a donation to the Django Software Foundation,
sponsoring via GitHub Sponsors,
or buying official merchandise.
## Contents
- [Third-Party Packages](#third-party-packages)
- [Admin](#admin)
- [Admin Themes](#admin-themes)
- [APIs](#apis)
- [Async](#async)
- [Caching](#caching)
- [Commands](#commands)
- [Configuration](#configuration)
- [Content Management Systems](#content-management-systems)
- [Database Connectors](#database-connectors)
- [Dependency Injection](#dependency-injection)
- [ECommerce](#ecommerce)
- [Editors](#editors)
- [Files/Images](#filesimages)
- [Forms](#forms)
- [Full-stack frameworks](#full-stack-frameworks)
- [General](#general)
- [Internationalisation (i18n)](#internationalisation-i18n)
- [Logging](#logging)
- [Monitoring](#monitoring)
- [Mailing](#mailing)
- [Model Fields](#model-fields)
- [Models](#models)
- [Performance](#performance)
- [Permissions](#permissions)
- [Search](#search)
- [Search Engine Optimisation](#search-engine-optimisation)
- [Security](#security)
- [Static Assets](#static-assets)
- [Task Queues](#task-queues)
- [Templates](#templates)
- [Testing](#testing)
- [URLs](#urls)
- [Users](#users)
- [Views](#views)
- [Python Packages](#python-packages)
- [Resources](#resources)
- [Official Resources](#official-resources)
- [Educational](#educational)
- [Community](#community)
- [Conferences](#conferences)
- [Job Boards](#job-boards)
- [Newsletters](#newsletters)
- [Podcasts](#podcasts)
- [Videos](#videos)
- [Books](#books)
- [Hosting](#hosting)
- [PaaS (Platforms-as-a-Service)](#paas-platforms-as-a-service)
- [IaaS (Infrastructure-as-a-Service)](#iaas-infrastructure-as-a-service)
- [Projects](#projects)
- [Boilerplate](#boilerplate)
- [Open Source Projects](#open-source-projects)
- [Django REST Framework](#django-rest-framework)
- [DRF Resources](#drf-resources)
- [DRF Tutorials](#drf-tutorials)
- [Wagtail](#wagtail)
- [Wagtail Resources](#wagtail-resources)
## Third-Party Packages
_For a complete listing of all available packages, see [Django Packages](https://djangopackages.org/)_
### Admin
- [django-hijack](https://github.com/django-hijack/django-hijack) - Admins can log in and work on behalf of other users without having to know their credentials.
- [django-import-export](https://github.com/django-import-export/django-import-export) - Django application and library for importing and exporting data with admin integration.
- [django-admin-inline-paginator-plus](https://github.com/DmytroLitvinov/django-admin-inline-paginator-plus) - A simple way to paginate your inline in Django admin
- [django-loginas](https://github.com/skorokithakis/django-loginas) - "Log in as user" for the Django admin.
- [impostor](https://github.com/avallbona/Impostor) - Impostor is a Django application which allows staff members to log in as a different user by using their own username and password.
- [django-impersonate](https://pypi.org/project/django-impersonate/) - Allow superusers to “impersonate” other non-superuser accounts.
- [django-admin-env-notice](https://github.com/dizballanze/django-admin-env-notice) - Visually distinguish environments in Django Admin, for example: `development`, `staging`, `production`.
- [django-related-admin](https://github.com/PetrDlouhy/django-related-admin) - A helper library that allows you to write list_displays across foreign key relationships.
- [django-admin-sortable2](https://github.com/jrief/django-admin-sortable2) - Generic drag-and-drop ordering for objects in the Django admin interface.
- [django-admin-collaborator](https://github.com/brktrlw/django-admin-collaborator) - Add real-time user presence, edit locks, and chat to Django admin with Channels and Redis.
- [dj-control-room](https://github.com/yassi/dj-control-room) - Build a control plane with a suite of operational tools inside the Django admin (Redis, cache, Celery, URLs, and more).
### Admin Themes
- [django-grappelli](https://github.com/sehmaschine/django-grappelli) - A jazzy skin for the admin.
- [django-jazzmin](https://github.com/farridav/django-jazzmin) - Drop-in theme for django admin, that utilises AdminLTE 3 & Bootstrap 4 to make yo' admin look jazzy.
- [django-admin-interface](https://github.com/fabiocaccamo/django-admin-interface) - Customize Admin by the admin itself(color, header. title,logo) and popup windows replaced by modals.
- [django-semantic-admin](https://github.com/globophobe/django-semantic-admin) - Django Semantic UI admin theme.
- [django-jet-reboot](https://github.com/assem-ch/django-jet-reboot) - Django Jet is modern template for Django admin interface with improved functionality.
- [django-baton](https://github.com/otto-torino/django-baton) - A cool, modern and responsive django admin application based on bootstrap 5.
- [django-unfold](https://github.com/unfoldadmin/django-unfold) - Modern Django admin theme for seamless interface development.
- [django-daisy](https://github.com/hypy13/django-daisy) - A modern django dashboard fully responsive built with daisyui.
- [django-admin-dracula](https://github.com/sjbitcode/django-admin-dracula) - 🦇 Dracula themes for the Django admin.
- [django-smartbase-admin](https://github.com/SmartBase-SK/django-smartbase-admin) - Django SmartBase Admin 🚀 performance-tuned 👥 end-user ready beautiful admin panel
### APIs
- [django-rest-framework](https://github.com/encode/django-rest-framework) - Web APIs for Django.
- [django-cors-headers](https://github.com/adamchainz/django-cors-headers) - If your back-end and front-end are on different servers, you need this.
- [dj-rest-auth](https://github.com/iMerica/dj-rest-auth) - Authentication for Django Rest Framework.
- [django-rest-knox](https://github.com/jazzband/django-rest-knox) - Authentication Module for django-rest-auth.
- [djoser](https://github.com/sunscrapers/djoser) - REST implementation of Django auth.
- [djaq](https://github.com/paul-wolf/djaq) - An instant remote API to Django models with a powerful query language.
- [django-rest-framework-simplejwt](https://github.com/jazzband/djangorestframework-simplejwt) - JSON web tokens for DRF.
- [django-webpack-loader](https://github.com/django-webpack/django-webpack-loader) - Transparently use webpack with Django.
- [drf-yasg](https://github.com/axnsan12/drf-yasg) - Automated generation of real Swagger/OpenAPI 2.0 schemas from Django REST Framework code.
- [graphene-django](https://github.com/graphql-python/graphene-django) - GraphQL for Django.
- [graphene-django-filter](https://github.com/devind-team/graphene-django-filter) - Advanced filters implementing and/or/not operators in GraphQL for Django.
- [django-ninja](https://django-ninja.rest-framework.com/) - Django Ninja - Fast Django REST framework based on type annotations.
- [django-tastypie](https://github.com/django-tastypie/django-tastypie) - Creating delicious APIs for Django apps since 2010.
- [drf-spectacular](https://github.com/tfranzel/drf-spectacular) - Sane and flexible OpenAPI 3 schema generation for Django REST framework.
- [django-webhook](https://github.com/danihodovic/django-webhook) - A plug-and-play Django app for sending outgoing webhooks on model changes.
- [strawberry-django](https://github.com/strawberry-graphql/strawberry-django) - Django integration with Strawberry, a GraphQL library designed for modern development
### Async
- [channels](https://github.com/django/channels/) - Async support for Django.
### Caching
- [django-cachalot](https://github.com/noripyt/django-cachalot) - Caches your Django ORM queries and automatically invalidates them.
- [django-cacheops](https://github.com/Suor/django-cacheops) - A slick ORM cache with automatic granular event-driven invalidation.
### Commands
- [django-extensions](https://github.com/django-extensions/django-extensions/) - Custom management extensions, notably `runserver_plus` and `shell_plus`.
- [django-click](https://github.com/django-commons/django-click) - Write Django management commands using the [click CLI library](https://click.palletsprojects.com).
- [django-dbbackup](https://github.com/Archmonger/django-dbbackup) - Management commands to help backup and restore your project database and media files.
- [django-liquidb](https://github.com/Gusakovskiy/django-liquidb) - Django application to simplify migration management and changes in states of db scheme.
- [django-migration-zero](https://github.com/ambient-innovation/django-migration-zero/) - Holistic implementation of "migration zero" pattern for Django covering local changes and in-production database adjustments.
- [django-typer](https://github.com/django-commons/django-typer) - Write Django management commands using the [Typer CLI library](https://typer.tiangolo.com).
### Configuration
- [confidential](https://github.com/candidco/confidential) - Manage configs and secrets (with CLI support).
- [django-environ](https://github.com/joke2k/django-environ) - Environment variables.
- [django-split-settings](https://github.com/wemake-services/django-split-settings) - Organize multiple settings files.
- [django-constance](https://github.com/jazzband/django-constance) - A Django app for storing dynamic settings in pluggable backends (Redis and Django model backend built in) with an integration with the Django admin app.
- [django-configurations](https://github.com/jazzband/django-configurations) - eases Django project configuration by relying on the composability of Python classes and following principles of [the twelve-factor app](https://12factor.net/config).
- [dynaconf](https://www.dynaconf.com/django/) - Dynaconf loads django settings from multiple sources (multiple file formats, env vars, redis, vault, etcd), manages secrets, and allows for different merging strategies all following [the twelve-factor app](https://12factor.net/config).
- [django-extra-settings](https://github.com/fabiocaccamo/django-extra-settings) - Config and manage typed extra settings using just the django admin.
- [django-removals](https://github.com/ambient-innovation/django-removals/) - Detect deprecated settings variables via convenient system checks
- [environs](https://github.com/sloria/environs) - Simplified environment variable parsing that comes with a [Django helper](https://github.com/sloria/environs#usage-with-django) that installs additional packages.
- [django-classy-settings](https://github.com/funkybob/django-classy-settings) - Class-based settings to keep your environments in order, with easy access to typed environment variables.
- [django-content-settings](https://django-content-settings.readthedocs.io/en/latest/) - Easily create and manage editable typed variables directly from the Django admin panel.
### Content Management Systems
- [wagtail](https://github.com/wagtail/wagtail) - Popular Django content management system (CMS). See [awesome-wagtail](https://github.com/springload/awesome-wagtail) too.
- [mezzanine](https://github.com/stephenmcd/mezzanine) - CMS framework.
- [django-cms](https://github.com/django-cms/django-cms) - CMS for Django.
- [feincms](https://github.com/feincms/feincms) - An extensible Django-based CMS.
- [puput](https://github.com/APSL/puput) - Blog app features with Wagtail.
### Database Connectors
- [djongo](https://github.com/doableware/djongo) - Django and MongoDB database connector.
### Dependency Injection
- [Wireup](https://github.com/maldoinc/wireup) - Dependency Injection for Django
### ECommerce
- [saleor](https://github.com/saleor/saleor) - GraphQL-based Django E-Commerce Platform.
- [django-oscar](https://github.com/django-oscar/django-oscar) - Domain-driven e-commerce for Django.
### Editors
- [django-markdownx](https://github.com/neutronX/django-markdownx) - Comprehensive Markdown plugin built for Django.
- [django-markdown-editor](https://github.com/agusmakmun/django-markdown-editor) - Awesome Django Markdown Editor, supported for Bootstrap & Semantic-UI.
- [django-business-logic](https://github.com/dgk/django-business-logic) - Visual DSL framework for Django.
- [django-summernote](https://github.com/lqez/django-summernote) - Summernote is a simple WYSIWYG editor.
- [django-tinymce](https://github.com/jazzband/django-tinymce) - TinyMCE integration for Django.
- [django-prose](https://github.com/withlogicco/django-prose) - A lightweight editor for content creation.
- [django-ace](https://github.com/django-ace/django-ace) - ACE integration for Django.
### Files/Images
- [django-cleanup](https://github.com/un1t/django-cleanup) - Zero configuration file/image removal for local and remote files.
- [django-imagekit](https://github.com/matthewwithanm/django-imagekit) - Django app for processing images for thumbnail, black-and-white and sizes.
- [django-pictures](https://github.com/codingjoe/django-pictures) - Responsive cross-browser image library using modern codes like AVIF & WebP.
- [sorl-thumbnail](https://github.com/jazzband/sorl-thumbnail) - Thumbnails for Django.
### Forms
- [django-crispy-forms](https://github.com/django-crispy-forms/django-crispy-forms/) - DRY Django forms.
- [django-floppyforms](https://github.com/jazzband/django-floppyforms) - Full control of form rendering.
- [django-formtools](https://github.com/jazzband/django-formtools) - For form previous and multistep forms, previously part of Django until 1.8.
- [django-widget-tweaks](https://github.com/jazzband/django-widget-tweaks) - Tweak form field rendering in templates.
- [django-autocomplete-light](https://github.com/yourlabs/django-autocomplete-light) - Add autocompletion to forms.
### Full-stack frameworks
- [Django LiveView](https://github.com/Django-LiveView/liveview) - Framework for creating dynamic, reactive interfaces server-side with Django templates. Real-time updates via WebSocket with decorator-based handlers.
- [Django-Bridge](https://github.com/kaedroho/django-bridge) - The simple way to build React frontends for Django applications.
- [ReactPy](https://github.com/reactive-python/reactpy) - It's React, but in Python. Insert dynamically rendered Python into Django templates using the [ReactPy-Django module](https://github.com/reactive-python/reactpy-django).
- [Reactor](https://github.com/edelvalle/reactor/) - Phoenix LiveView, but for Django.
- [Sockpuppet](https://sockpuppet.argpar.se/) - Build reactive applications with the Django tooling you already know and love.
- [Unicorn](https://www.django-unicorn.com/) - A reactive component framework that progressively enhances a normal Django view, makes AJAX calls in the background, and dynamically updates the DOM.
### General
- [django-data-browser](https://github.com/tolomea/django-data-browser) - Interactive, user-friendly database explorer.
- [django-filter](https://github.com/carltongibson/django-filter) - Powerful filters based on Django QuerySets.
- [django-sql-explorer](https://github.com/explorerhq/sql-explorer) - Share data via SQL queries.
- [django-tables2](https://github.com/jieter/django-tables2) - HTML tables with pagination/sorting.
- [django-maintenance-mode](https://github.com/fabiocaccamo/django-maintenance-mode) - Shows a 503 error page when maintenance-mode is on.
- [django-freeze](https://github.com/fabiocaccamo/django-freeze) - Convert your dynamic django site to a static one with one line of code.
- [django-nh3](https://github.com/marksweb/django-nh3) - Django integration with for nh3 and is an alternative for django-bleach.
- [Weblate](https://github.com/WeblateOrg/weblate) - Weblate is a copylefted libre software web-based continuous localization system, used by over 2500 libre projects and companies in more than 165 countries.
- [Django-Classy-Doc](https://github.com/nanuxbe/django-classy-doc) - Document your own code in the style of CCBV and CDRF.
- [iommi](https://github.com/iommirocks/iommi) - Toolkit for development of CRUD applications without writing HTML or JavaScript.
### Internationalisation (i18n)
- [django-localflavor](https://github.com/django/django-localflavor) - A collection of functionality that is useful for particular countries or cultures. Previously a part of the Django core.
- [django-modeltrans](https://github.com/zostera/django-modeltrans) - Translate Django model fields in a JSONField.
- [django-modeltranslations](https://github.com/deschler/django-modeltranslation) - Translates Django models using a registration approach.
- [django-rosetta](https://github.com/mbi/django-rosetta) - Rosetta provides a UI to read and write your project's gettext catalogs within the Django Admin.
### Logging
- [django-guid](https://github.com/snok/django-guid) - Inject a GUID (Correlation-ID) into every log message in a Django request.
- [DRF-API-Logger](https://github.com/vishalanandl177/DRF-API-Logger) - An API Logger for your Django Rest Framework project.
### Monitoring
- [django-prometheus](https://github.com/django-commons/django-prometheus) - Export Django monitoring metrics to Prometheus.
- [django-mixin](https://github.com/adinhodovic/django-mixin) - Monitoring mixin for Django-prometheus. A set of Grafana dashboards and Prometheus rules for Django.
### Mailing
- [django-pony-express](https://github.com/ambient-innovation/django-pony-express) - Class-based emails including a test suite for Django.
- [django-anymail](https://github.com/anymail/django-anymail) - Django email backends and webhooks for Amazon SES, Brevo (Sendinblue), MailerSend, Mailgun, Mailjet, Postmark, Postal, Resend, SendGrid, SparkPost, Unisender Go and more.
### Model Fields
- [django-colorfield](https://github.com/fabiocaccamo/django-colorfield) - Color field for django models with a nice color-picker widget.
- [django-model-utils](https://github.com/jazzband/django-model-utils) - Django model mixins and utilities.
- [django-money](https://github.com/django-money/django-money) - Money fields for forms/models.
- [django-phonenumber-field](https://github.com/stefanfoulis/django-phonenumber-field) - Model/form field for normalized phone numbers.
- [django-streamfield](https://github.com/raagin/django-streamfield) - Simple StreamField for plain Django admin (based on Wagtail CMS StreamField idea).
### Models
- [django-lifecycle](https://github.com/rsinger86/django-lifecycle) - Declarative model lifecycle hooks, an alternative to Signals.
- [django-mptt](https://github.com/django-mptt/django-mptt) - Modified Preorder Tree Traversal; working with trees of Model instances.
- [django-taggit](https://github.com/jazzband/django-taggit/) - Simple model tags.
- [django-reversion](https://github.com/etianen/django-reversion) - Version control for model instances.
- [django-simple-history](https://github.com/django-commons/django-simple-history) - Store model history and view/revert changes from the admin.
- [django-polymorphic](https://github.com/jazzband/django-polymorphic) - Django-polymorphic simplifies using inherited models in Django projects.
- [django-recurrence](https://github.com/jazzband/django-recurrence) - Utility for working with recurring dates in Django.
- [django-treenode](https://github.com/fabiocaccamo/django-treenode) - Abstract model/admin for tree-based stuff.
- [django-auto-prefetch](https://github.com/adamchainz/django-auto-prefetch) - Automatically prefetch foreign key values as needed.
### Performance
- [django-perf-rec](https://cur.at/GHUO6cn?m=web) - Keep detailed records of the performance of your Django code.
- [New Relic](https://newrelic.com/python/django) - Time middleware, views, and SQL queries.
- [Scout](https://scoutapm.com/docs/python/django) - Time middleware, template rendering, and SQL queries with automatic N+1 detection.
- [django-silk](https://github.com/jazzband/django-silk) - Live profiling and inspection of HTTP requests and database queries.
- [py-spy](https://github.com/benfred/py-spy) - Sampling profiler for Python programs.
- [pyinstrument](https://github.com/joerick/pyinstrument) - Call stack profiler for Python, Django, Flask, FastAPI.
- [django-zeal](https://github.com/taobojlen/django-zeal) - Detect N+1 queries with user-friendly error messages
### Permissions
- [django-role-permissions](https://github.com/vintasoftware/django-role-permissions) - Django app for role-based permissions management.
- [django-guardian](https://github.com/django-guardian/django-guardian) - Per object permissions in Django.
- [django-rules](https://github.com/dfunckt/django-rules) - A tiny but powerful app providing object-level permissions, built from the ground up for Django.
### Search
- [django-haystack](https://github.com/django-haystack/django-haystack) - Modular search for Django.
- [django-watson](https://github.com/etianen/django-watson) - Full-text search plugin.
- [django-admin-search](https://github.com/shinneider/django-admin-search) - Modal filter for django admin.
- [django-elasticsearch-dsl](https://github.com/django-es/django-elasticsearch-dsl) - Elasticsearch DSL integration for Django.
### Search Engine Optimisation
- [django-check-seo](https://github.com/kapt-labs/django-check-seo) - Check SEO of pages.
### Security
- [django-csp](https://github.com/mozilla/django-csp) - Adds [Content-Security-Policy](http://www.w3.org/TR/CSP/) headers to Django.
- [django-feature-policy](https://github.com/adamchainz/django-permissions-policy) - Set the draft security HTTP header `Feature-Policy` on a Django app.
- [django-protected-media](https://github.com/cobusc/django-protected-media) - Manages media that are considered sensitive in a protected fashion.
- [DJ Checkup](https://djcheckup.com) - Runs several checks on your deployed Django site to check for common security mistakes.
### Static Assets
- [django-storages](https://github.com/jschneier/django-storages) - A single library to support multiple custom storage backends for Django.
- [django-compressor](https://github.com/django-compressor/django-compressor/) - Compress JavaScript/CSS into a single cached file.
- [easy-thumbnails](https://github.com/SmileyChris/easy-thumbnails) - Image thumbnails for Django.
- [whitenoise](https://github.com/evansd/whitenoise) - Simplified static file serving for Python websites.
### Task Queues
- [django-q2](https://github.com/django-q2/django-q2) - A multiprocessing distributed task queue for Django.
- [django-rq](https://github.com/rq/django-rq) - Integration for Redis Queue.
- [django-redis](https://github.com/jazzband/django-redis) - Full-featured Redis cache backend for Django.
- [celery](https://github.com/celery/celery) - Robust and broker-agnostic task queues for bigger, performance-focused projects.
- [flower](https://github.com/mher/flower) - Flower is a web-based tool for monitoring and administrating Celery clusters.
- [django-celery-beat](https://github.com/celery/django-celery-beat) - A periodic task scheduler with database configured by Django's Admin Panel.
- [celery-exporter](https://github.com/danihodovic/celery-exporter) - Prometheus & Grafana monitoring of Celery tasks.
- [django-dramatiq](https://github.com/Bogdanp/django_dramatiq) - Task processing library with a focus on simplicity, reliability, and performance.
- [django-celery-results](https://github.com/celery/django-celery-results) - Celery result backend with Django.
- [django-tasks](https://github.com/realOrangeOne/django-tasks) - A reference implementation and backport of background workers and tasks in Django, based on [DEP 14](https://www.djangoproject.com/weblog/2024/may/29/django-enhancement-proposal-14-background-workers/).
### Templates
- [django-components](https://github.com/django-components/django-components/) - A way to create simple reusable template components in Django.
- [django-template-partials](https://github.com/carltongibson/django-template-partials/) - Reusable named inline partials for the Django Template Language.
- [slippers](https://mitchel.me/slippers/) - Build reusable components in Django without writing a single line of Python.
- [JinjaX](https://jinjax.scaletti.dev/) - Super components powers for your Jinja templates.
- [django-cotton](https://django-cotton.com/) - Goodbye `{% raw %}{%{% endraw %} extends, block, include {% raw %}%}{% endraw %}`, Hello ``. Bringing modern UI composition to Django.
- [htpy](https://htpy.dev/) - htpy is a library that makes writing HTML in plain Python fun and efficient, without a template language.
- [django-suspense](https://github.com/paqstd-dev/django-suspense) - Easy way to display a fallback in templates until children have finished loading (like React).
### Testing
- [django-debug-toolbar](https://github.com/django-commons/django-debug-toolbar/) - Configurable panels to debug requests/responses.
- [pytest-django](https://github.com/pytest-dev/pytest-django) - Use pytest features in Django.
- [django-test-migrations](https://github.com/wemake-services/django-test-migrations) - Test django schema and data migrations, including migrations' order.
- [django-test-plus](https://github.com/revsys/django-test-plus/) - Useful additions to Django's default TestCase.
- [factory-boy](https://github.com/FactoryBoy/factory_boy) - Test fixtures replacement.
- [django-waffle](https://github.com/django-waffle/django-waffle) - A feature flipper for Django.
- [model-bakery](https://github.com/model-bakers/model_bakery) - Object factory for Django (rename of legacy Model Mommy project).
- [django-fakery](https://github.com/fcurella/django-fakery) - An easy-to-use implementation of Creation Methods for Django, backed by Faker.
- [drf-openapi-tester](https://github.com/snok/drf-openapi-tester) - Django test utility for validating Swagger 2.0 and OpenAPI 3.0 documentation.
- [django-pattern-library](https://github.com/torchbox/django-pattern-library) - Pattern library generator for Django templates, to help testing of UI components.
- [storybook-django](https://github.com/torchbox/storybook-django) - Develop Django UI components in isolation, with Storybook.
### URLs
- [dj-database-url](https://github.com/jazzband/dj-database-url) - Database URLs.
- [urlman](https://github.com/andrewgodwin/urlman) - A nicer way to do URLs for Django models.
- [django-robots](https://github.com/jazzband/django-robots) - This is a basic Django application to manage robots.txt files following the robots exclusion protocol, complementing the Django Sitemap contrib app.
- [django-redirects](https://github.com/fabiocaccamo/django-redirects) - Redirects as they should be, with full control.
### Users
- [django-allauth](https://github.com/pennersr/django-allauth/) - Improved user registration including social auth.
- [django-allauth-ui](https://github.com/danihodovic/django-allauth-ui/) - Better-looking templates for django-allauth.
- [django-improved-user](https://github.com/jambonrose/django-improved-user) - A custom Django user that authenticates via email. Follows identity and authentication best practices.
- [django-organizations](https://github.com/bennylope/django-organizations/) - Multi-user accounts for Django projects.
- [django-cas-ng](https://github.com/django-cas-ng/django-cas-ng) - Django-cas-ng is Django CAS (Central Authentication Service) 1.0/2.0/3.0 client library to support SSO (Single Sign On) and Single Logout (SLO).
- [django-guest-user](https://github.com/julianwachholz/django-guest-user) - Allow visitors to use your site like a regular user and register later.
### Views
- [django-braces](https://github.com/brack3t/django-braces) - Reusable, generic mixins.
- [django-easy-audit](https://github.com/soynatan/django-easy-audit) - Keep track of user actions.
- [django-extra-views](https://github.com/AndrewIngram/django-extra-views) - Extra class-based generic views.
- [django-stronghold](https://github.com/mgrouchy/django-stronghold) - Makes all your Django views default login_required.
- [neapolitan](https://github.com/carltongibson/neapolitan) - Quick CRUD views for Django.
## Developer Tools
Standalone tools that help in developing Django projects.
### Templates
- [curlylint](https://www.curlylint.org/) - Experimental HTML templates linting for Jinja, Nunjucks, Django templates, Twig, Liquid.
- [djhtml](https://github.com/rtts/djhtml) - Django/Jinja template indenter.
- [djlint](https://www.djlint.com/) - Lint & Format HTML Templates.
## Python Packages
_A short list of Python packages that work well with Django._
- [bleach](https://github.com/mozilla/bleach) - Sanitize your inputs/forms.
- [black](https://github.com/psf/black) - Uncompromising Python code formatter.
- [coveragepy](https://github.com/coveragepy/coveragepy) - Code coverage measurement.
- [faker](https://github.com/joke2k/faker) - Faker is a Python package that generates fake data for you.
- [huey](https://github.com/coleifer/huey) - A little task queue for Python.
- [pillow](https://github.com/python-pillow/Pillow) - Python Imaging Library.
- [pytest](https://github.com/pytest-dev/pytest/) - Testing framework.
- [python-decouple](https://github.com/HBNetwork/python-decouple) - Strict separation of settings from code.
- [python-slugify](https://github.com/un33k/python-slugify) - Returns unicode slugs.
- [sentry-python](https://github.com/getsentry/sentry-python) - Error reporting SDK.
- [python-socketio](https://github.com/miguelgrinberg/python-socketio) - Python implementation of the Socket.IO_ realtime client and server. [(create Socket.io Django server instance)](https://python-socketio.readthedocs.io/en/latest/server.html?highlight=django#creating-a-server-instance)
- [Ruff](https://github.com/astral-sh/ruff) - An extremely fast Python linter and code formatter, written in Rust.
## Resources
### Official Resources
- [Project Website](https://www.djangoproject.com/) - Official Django website.
- [Documentation](https://docs.djangoproject.com/en/dev/) - Comprehensive documentation for all Django versions.
- [Polls Tutorial](https://docs.djangoproject.com/en/dev/intro/tutorial01/) - Build a polls tutorial while learning Django internals.
- [Source Code](https://github.com/django/django/) - Hosted on GitHub.
### Educational
- [Django Girls Tutorial](https://tutorial.djangogirls.org/en/) - Use function-based views to build a blog app.
- [LearnDjango](https://learndjango.com/) - Tutorials and premium courses on Django and Django REST Framework.
- [Adam Johnson](https://adamj.eu/tech/) - Adam is on the Technical Board of Django and regularly writes tutorials.
- [Photon Designer - Django tutorials](https://photondesigner.com/articles) - Django tutorials by Tom Dekan on how to build Django apps simply - from how to build an instant messenger with Django, add instant search, to using Google Drive as a database. Updated regularly.
- [TestDriven](https://testdriven.io/blog/) - Multiple Django-specific tutorials on topics like Docker, payments, and more.
- [Classy Class-Based Views](https://ccbv.co.uk/) - Detailed descriptions of methods/properties/attributes for each generic class-based view.
- [Classy Django REST Framework](http://www.cdrf.co) - Detailed descriptions with methods/attributes for DRF class-based views and serializers.
- [Simple is Better than Complex](https://simpleisbetterthancomplex.com/) - Regularly updated website with many tutorials and tips on Django.
- [Full Stack Python's Django Page](https://www.fullstackpython.com/django.html) - Explanation of Django philosophy and links to other resources and tutorials.
- [RealPython](https://realpython.com/tutorials/django/) - Many high-quality tutorials on Django.
- [Mozilla Tutorial](https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django) - Create a lending library app.
- [Matt Layman](https://www.mattlayman.com) - Regular tutorials and deep-dives on Django topics.
- [Django Styleguide](https://github.com/HackSoftware/Django-Styleguide) - Styleguide for Django with best practices and examples.
- [Django Template Tags and Filters](https://www.djangotemplatetagsandfilters.com/) - Additional docs on Django's 57 built-in template filters and 27 template tags.
- [Django for Everybody](https://www.dj4e.com/) - A complete course for webdev beginners focused on Django.
- [CS50W](https://cs50.harvard.edu/web/2020/) - Harvard's University introductory course to web development, it explains Django as backend framework.
### Community
- [Django Forum](https://forum.djangoproject.com/) - Official Discourse board.
- [Community Page](https://www.djangoproject.com/community/) - Featuring feeds of Community Blog Posts, Jobs, and more.
- [Local Django Communities Page](https://www.djangoproject.com/community/local/) - Featuring local events all around the world.
- [Django Users Google Group](https://groups.google.com/forum/#!forum/django-users/) - Very active discussion board for questions/answers.
- [Developers Google Group](https://groups.google.com/forum/#!forum/django-developers/) - For contributions to Django itself only.
- [Mastodon](https://fosstodon.org/@django) - For official announcements on updates, security fixes, etc.
- [X (formerly Twitter)](https://x.com/djangoproject/) - For official announcements on updates, security fixes, etc.
- [Discord Server](https://discord.com/invite/xcRH6mN4fa) - Django Discord Community.
- IRC Channel - Chat with other Django users at irc://irc.freenode.net/django.
- [Djangonaut Space](https://djangonaut.space) - Free peer-mentoring program for the Django community to launch people into the universe of open source contributions.
### Conferences
- [DjangoCon US](https://djangocon.us/) ([YouTube Channel](https://www.youtube.com/channel/UC0yY6a79pPY9J0ShIHRf6yw))
- [DjangoCon Europe](https://djangocon.eu/) ([YouTube Channel](https://www.youtube.com/user/djangoconeurope))
- [DjangoCon AU](https://djangocon.com.au/)
- [DjangoCon Africa](https://djangocon.africa/)
- [Django Day Copenhagen](https://djangoday.dk/) ([YouTube Channel](https://www.youtube.com/@djangodanmark))
- [PyCon US](https://us.pycon.org/) ([YouTube Channel](https://www.youtube.com/channel/UCsX05-2sVSH7Nx3zuk3NYuQ))
- [PyCon Australia](https://pycon-au.org/) ([YouTube Channel](https://www.youtube.com/user/PyConAU))
- [Euro Python](https://europython.eu/) ([YouTube Channel](https://www.youtube.com/user/PythonItalia))
- [Django Under the Hood](https://www.youtube.com/channel/UC9T1dhIlL_8Va9DxvKRowBw/videos)
- [DjangoCongress JP](https://djangocongress.jp/) ([YouTube Channel](https://www.youtube.com/@djangocongressjp3623))
- [Complete listing of all PyCons globally](https://pycon.org)
### Job Boards
- [Django Job Board](https://djangojobboard.com/) - A Django job board that also aggregates other job boards. Formerly Django News Jobs.
- [Django Gigs](https://djangogigs.com) - This platform caters specifically to freelance and full-time Django developers.
- [Django Jobs](https://djangojobs.net) - Django jobs posting for hiring Django Python developers.
- [Python.org Job Boards](https://www.python.org/jobs/) - While not exclusively for Django, this job board is hosted by the official Python website and features a range of Python and Django-related job opportunities.
### Newsletters
- [Django News](https://django-news.com) - Weekly newsletter on announcements, articles, projects, and talks.
### Podcasts
- [Django Chat](https://djangochat.com/) - A weekly podcast from William Vincent and Django Fellow Carlton Gibson with discussions of core Django concepts and regular guests.
- [Django Brew](https://djangobrew.com/) - A fun, caffeine-powered podcast about the Django web framework by Adam Hill and Sangeeta Jadoonanan.
- [TalkPython](https://talkpython.fm/) - The leading Python podcast with occassional episodes on Django.
- [Running in Production](https://runninginproduction.com/tags/django) - No longer active, but a great backlog of episodes on Django tech stacks.
### Videos
- [DjangoTV](https://djangotv.com) - Your source for Django conference videos and tutorials.
- [PyVideo](https://pyvideo.org) - PyVideo is an index of Python related media.
### Books
For a complete listing of in-print books, check out [DjangoBook.com](https://djangobook.com/).
_Django 5_
- [Django for APIs, Fifth Edition](https://learndjango.com/courses/django-for-apis/)
- [Boost Your Django DX](https://adamchainz.gumroad.com/l/byddx)
- [Django 5 By Example](https://www.packtpub.com/en-us/product/django-5-by-example-9781805125457)
- [Django in Action](https://www.manning.com/books/django-in-action)
- [Django for Beginners, Fifth Edition](https://learndjango.com/courses/django-for-beginners/)
## Hosting
### PaaS (Platforms-as-a-Service)
- [Appliku](https://appliku.com)
- [Dokku](https://dokku.com)
- [Divio](https://www.divio.com)
- [Fly](https://fly.io)
- [Google Cloud](https://cloud.google.com/python/django/)
- [Heroku](https://www.heroku.com)
- [Microsoft Azure](https://azure.microsoft.com/en-us/develop/python/)
- [Piku](https://github.com/piku/piku)
- [Platform.sh](https://platform.sh)
- [PythonAnywhere](https://www.pythonanywhere.com)
- [Railway](https://railway.app)
- [Render](https://render.com)
- [Vercel](https://vercel.com/home)
### IaaS (Infrastructure-as-a-Service)
- [Digital Ocean](https://www.digitalocean.com)
- [Linode](https://www.linode.com)
- [Amazon Lightsail](https://aws.amazon.com/lightsail/)
- [Hetzner](https://www.hetzner.com)
## Projects
### Boilerplate
- [cookiecutter-django](https://github.com/cookiecutter/cookiecutter-django/) - A full-bodied starter project, highly customizable.
- [django-base-site](https://github.com/epicserve/django-base-site/) - A Django site with many common third-party packages pre-installed.
- [djangox](https://github.com/wsvincent/lithium/) - Batteries included starter project for Pip, Pipenv, or Docker.
- [django-docker-template](https://github.com/amerkurev/django-docker-template) - Dockerized Django with Postgres, Gunicorn, and Traefik (with auto-renew Let's Encrypt).
- [django-startproject](https://github.com/jefftriplett/django-startproject) - Django start project template with batteries.
- [wemake-django-template](https://github.com/wemake-services/wemake-django-template/) - Bleeding-edge Django template focused on code quality and security.
- [cookiecutter-vue-django](https://github.com/ilikerobots/cookiecutter-vue-django) - Django + Vue starter project fusing Vue SFCs & Django Templates.
- [sidewinder](https://github.com/stribny/sidewinder/) - A Django starter kit that focuses on good defaults, developer experience, and deployment.
- [Falco](https://github.com/falcopackages/falco-cli) - Enhance your Django developer experience: CLI and Guides for the Modern Django Developer.
- [BH2](https://codeberg.org/trey/bh2) - Get a new Django site started in a Djiffy
- [django-react-boilerplate](https://github.com/vintasoftware/django-react-boilerplate) - A Django, React, Tailwind, Webpack project boilerplate
### Open Source Projects
- [Blog app with users and forms](https://github.com/wsvincent/djangoforbeginners/tree/master/ch7-blog-app-with-users/)
- [Newspaper app with custom user model, full user auth](https://github.com/wsvincent/djangoforbeginners/tree/master/ch15-comments)
- [Behavior-Driven Development with Aloe](https://github.com/testdrivenio/django-aloe-bdd/)
- [Image Sharing Blog](https://github.com/MeNsaaH/soMedia)
- [Bootcamp: An enterprise social network](https://github.com/vitorfs/bootcamp)
- [Zulip](https://github.com/zulip/zulip/) - Open-source team chat.
- [django-job-portal](https://github.com/manjurulhoque/django-job-portal) - Job portal application using Django.
- [Built with Django](https://builtwithdjango.com) - Curated list of awesome Django projects.
- [PostHog](https://github.com/PostHog/posthog) - Open-source product analytics.
- [HyperKitty](https://gitlab.com/mailman/hyperkitty) - A web interface to access GNU Mailman v3 archives.
- [Healthchecks](https://github.com/healthchecks/healthchecks) - A Cron Monitoring Tool written in Python & Django.
- [Flagsmith](https://github.com/Flagsmith/flagsmith) - Open-source Feature Flagging, Remote Config, and AB testing.
- [OpenContracts](https://github.com/Open-Source-Legal/OpenContracts) - Enterprise-grade document analytics platform that combines automated PDF parsing, vector embeddings, and LLM integration.
- [Baserow](https://gitlab.com/baserow/baserow) - Open source no-code database and Airtable alternative built with Django and Vue.js.
- [Django CRM Admin](https://github.com/DjangoCRM/django-crm) - Open source Python CRM built entirely on Django Admin Site.
- [linkding](https://github.com/sissbruecker/linkding) - Self-hosted bookmark manager that is designed to be minimal, fast, and easy to set up using Docker.
- [pythonic-news](https://github.com/sebst/pythonic-news) - Hacker News clone.
## Django REST Framework
_The most popular way to build web APIs with Django._
### DRF Resources
- [Official Documentation](https://www.django-rest-framework.org/)
- [DRF Source Code](https://github.com/encode/django-rest-framework)
- [awesome-django-rest-framework](https://github.com/nioperas06/awesome-django-rest-framework)
### DRF Tutorials
- [Official REST Framework - A Beginner's Guide](https://learndjango.com/tutorials/official-django-rest-framework-tutorial-beginners)
- [Building APIs with Django and DRF](https://books.agiliq.com/projects/django-api-polls-tutorial/en/latest/)
- [DRF with React](https://www.valentinog.com/blog/drf/)
- [Making React and Django play well together](https://fractalideas.com/blog/making-react-and-django-play-well-together/)
## Wagtail
_Wagtail, the powerful CMS for modern websites._
### Wagtail Resources
- [Official website](https://wagtail.org/)
- [Developer documentation](https://docs.wagtail.org/en/stable/)
- [User documentation](https://guide.wagtail.org/en-latest/)
- [Wagtail Source Code](https://github.com/wagtail/wagtail/)
- [awesome-wagtail](https://github.com/springload/awesome-wagtail)
- [This week in Wagtail](https://wagtail.org/this-week-in-wagtail/) - A (most) weekly email with updates from the Wagtail core team.
- [Wagtail Space](https://www.wagtail.space/) - Wagtail conferences around the world.
- [Wagtail events](https://wagtail.org/events/) - Online and in-person Wagtail events.
================================================
FILE: _config.yml
================================================
assets:
cachebust: hard
title: Awesome Django
email: your-email@example.com
description: >-
A curated list of awesome things related to Django. Maintained by
William Vincent and Jeff Triplett
baseurl: ""
url: "https://awesomedjango.org"
# Build settings
markdown: kramdown
remote_theme: pmarsceill/just-the-docs
plugins:
- jekyll-feed
- jekyll-optional-front-matter
- jekyll-seo-tag
include:
- "_projects"
- README.md
exclude:
- "*.md"
- "*.py"
- docker*
- Gemfile*
- justfile
- LICENSE
- Makefile
- modd.conf
- node_modules
- package*.json
- requirements.*
- scripts
- src
- vendor
defaults:
- scope:
path: "" # an empty string here means all files in the project
values:
layout: "default"
- scope:
path: "README.md"
values:
permalink: "/"
layout: "default"
collections: # process the _data folder
components:
output: false
projects:
output: false
permalink: /:collection/:name/
aux_links:
"Awesome Django on GitHub":
- "//github.com/wsvincent/awesome-django"
# Makes Aux links open in a new tab. Default is false
aux_links_new_tab: false
color_scheme: django
# color_scheme: light
heading_anchors: true
footer_content: >-
Awesome Django is not associated with the Django Software Foundation.
Django is a registered trademark of the Django Software Foundation.
# Footer last edited timestamp
last_edit_timestamp: true # show or hide edit time - page must have `last_modified_date` defined in the frontmatter
last_edit_time_format: "%b %e %Y at %I:%M %p" # uses ruby's time format: https://ruby-doc.org/stdlib-2.7.0/libdoc/time/rdoc/Time.html
# Footer "Edit this page on GitHub" link text
gh_edit_link: true # show or hide edit this page link
gh_edit_link_text: "Edit this page on GitHub."
gh_edit_repository: "https://github.com/wsvincent/awesome-django" # the github URL for your repo
gh_edit_branch: "main" # the branch that your docs is served from
# gh_edit_source: docs # the source that your files originate from
gh_edit_view_mode: "tree" # "tree" or "edit" if you want the user to jump into the editor immediately
search_enabled: false
search:
# Split pages into sections that can be searched individually
# Supports 1 - 6, default: 2
heading_level: 2
# Maximum amount of previews per search result
# Default: 3
previews: 3
# Maximum amount of words to display before a matched word in the preview
# Default: 5
preview_words_before: 5
# Maximum amount of words to display after a matched word in the preview
# Default: 10
preview_words_after: 10
# Set the search token separator
# Default: /[\s\-/]+/
# Example: enable support for hyphenated search words
tokenizer_separator: /[\s/]+/
# Display the relative url in search results
# Supports true (default) or false
rel_url: true
# Enable or disable the search button that appears in the bottom right corner of every page
# Supports true or false (default)
button: false
nav_external_links:
- title: Third-Party Packages
url: "#third-party-packages"
hide_icon: true
- title: Python Packages
url: "#python-packages"
hide_icon: true
- title: Resources
url: "#resources"
hide_icon: true
- title: Hosting
url: "#hosting"
hide_icon: true
- title: Projects
url: "#projects"
hide_icon: true
- title: Django REST Framework
url: "#django-rest-framework"
hide_icon: true
- title: Wagtail
url: "#wagtail"
hide_icon: true
================================================
FILE: _includes/head_custom.html
================================================
================================================
FILE: _sass/color_schemes/django.scss
================================================
// Django Brand Colors
$django-green-dark: #0C4B33;
$django-green-mid: #20AA76;
$django-green-light: #44B78B;
$django-green-pale: #E8F5F0;
$django-cream: #F9F7F3;
// Theme Configuration
$color-scheme: light;
// Body & Text
$body-background-color: $white;
$body-heading-color: $django-green-dark;
$body-text-color: #333333;
// Links & Buttons
$link-color: $django-green-mid;
$btn-primary-color: $django-green-dark;
$base-button-color: $django-green-pale;
// Sidebar & Navigation
$sidebar-color: $django-green-pale;
$nav-child-link-color: $django-green-dark;
// Code Blocks
$code-background-color: $django-cream;
// Search & Tables
$search-background-color: $white;
$search-result-preview-color: #666666;
$table-background-color: $white;
$feedback-color: darken($django-green-pale, 5%);
================================================
FILE: compose.yml
================================================
services:
devd:
image: ghcr.io/jefftriplett/devd:latest
command: ["--livewatch"]
init: true
ports:
- 8000:8000
volumes:
- .:/srv/jekyll:cached
jekyll:
image: jekyll/jekyll:latest
command: ["jekyll", "serve", "--host", "0.0.0.0", "--port", "4000", "--livereload", "--drafts", "--force_polling"]
environment:
- BUNDLE_PATH=/usr/local/bundle
expose:
- 4000
init: true
ports:
- 4000:4000
volumes:
- .:/srv/jekyll:cached
- ./.vendor/bundle:/usr/local/bundle:cached
================================================
FILE: contributing.md
================================================
# Contribution Guidelines
Contributions are welcome! Please note that Will and Jeff work on this as a benefit to the Django community. It is based on our own personal, biased thoughts.
If you disagree with choices made, you are welcome to fork this repo and create/maintain your own list of awesome Django resources if you disagree with choices I've made.
That said, we will review any and all contributions. Here's the process:
1. Make an individual pull request for each suggestion and include a reason why it is awesome.
2. To be fair, the order is first-come-first-serve so unless a section is alphabetical, add the item at the end.
3. If you think something belongs in the wrong category, or think there needs to be a new category, feel free to edit things too.
================================================
FILE: justfile
================================================
# Default recipe - lists all available recipes
@_default:
just --list
# Run alex linter on README.md to find inconsiderate writing
@alex:
bunx alex README.md
# Install and update dependencies
@bootstrap:
python -m pip install --upgrade pip uv
uv pip install --upgrade --requirement pyproject.toml
# Generate table of contents and build the Jekyll site
@build:
just doctoc
bundle exec jekyll build
# Generate table of contents for README.md
@doctoc:
bunx doctoc README.md
# Stop the Docker containers
@down:
docker compose down
# Run linting on all files
@lint *ARGS:
# -uv --quiet tool run curlylint _layouts/
# -bunx awesome-lint README.md
uv tool run --with pre-commit-uv pre-commit run {{ ARGS }} --all-files
# Start local development server
@serve:
# modd --file=modd.conf
just up ""
# Start containers (detached by default)
@start *ARGS="--detach":
just up {{ ARGS }}
# Start Docker containers with optional arguments
@up *ARGS:
docker compose up {{ ARGS }}
================================================
FILE: modd.conf
================================================
{
# prep: "killall ruby"
daemon +sigterm: "bundle exec jekyll serve --drafts --watch --port 4000"
}
# DEVD proxy with livereload listening on port 8000
**/*.css
**/*.html
**/*.js
!src/**
{
daemon: "devd --modd -l http://localhost:4000"
}
# src/*.css
# src/*.js
# {
# prep +onchange: "just static"
# }
================================================
FILE: pyproject.toml
================================================
[project]
name = "awesome-django"
version = "0.1.0"
description = "A curated list of awesome things related to Django. Maintained by [Will Vincent](https://github.com/wsvincent) and [Jeff Triplett](https://github.com/jefftriplett)."
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"mkdocs",
"mkdocs-material",
"requests",
"rich",
"typer",
]
================================================
FILE: scripts/main.py
================================================
#!/usr/bin/env -S uv --quiet run --script
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "bs4",
# "httpx",
# "pydantic",
# "python-dateutil",
# "python-frontmatter",
# "python-slugify",
# "pytz",
# "rich",
# "typer",
# "markdown-it-py",
# "sqlmodel",
# ]
# ///
import json
import os
import re
from datetime import datetime
from pathlib import Path
from typing import Any
from typing import Optional
from urllib.parse import urlparse
import frontmatter
import httpx
import typer
from bs4 import BeautifulSoup
from bs4 import Tag
from markdown_it import MarkdownIt
from pydantic import BaseModel
from pydantic import ConfigDict
from pydantic import Field
from rich import print
from rich.console import Console
from rich.progress import track
from rich.table import Table
from slugify import slugify
from sqlmodel import Field as SQLField
from sqlmodel import Session
from sqlmodel import SQLModel
from sqlmodel import create_engine
from sqlmodel import select
app = typer.Typer(
add_help_option=False,
no_args_is_help=True,
rich_markup_mode="rich",
)
class Project(BaseModel):
"""Model representing a Django project from the awesome list."""
model_config = ConfigDict(extra="allow")
name: str
description: str
url: str
category: str
slug: str = Field(default="")
tags: list[str] = Field(default_factory=list)
github_stars: int | None = None
github_forks: int | None = None
github_last_update: str | None = None
github_last_commit: str | None = None
previous_urls: list[str] = Field(default_factory=list)
def __init__(self, **data):
super().__init__(**data)
if not self.slug:
self.slug = slugify(self.name)
# SQLModel database model
class ProjectDB(SQLModel, table=True):
"""SQLModel for storing projects in SQLite database."""
__tablename__ = "projects"
id: Optional[int] = SQLField(default=None, primary_key=True)
name: str = SQLField(index=True)
description: str
url: str = SQLField(unique=True)
category: str = SQLField(index=True)
slug: str = SQLField(unique=True, index=True)
tags: str = SQLField(default="[]") # JSON string
github_stars: Optional[int] = SQLField(default=None, index=True)
github_forks: Optional[int] = SQLField(default=None)
github_last_update: Optional[str] = SQLField(default=None)
github_last_commit: Optional[str] = SQLField(default=None, index=True)
previous_urls: str = SQLField(default="[]") # JSON string
@classmethod
def from_project(cls, project: Project) -> "ProjectDB":
"""Convert a Project to ProjectDB."""
return cls(
name=project.name,
description=project.description,
url=project.url,
category=project.category,
slug=project.slug,
tags=json.dumps(project.tags),
github_stars=project.github_stars,
github_forks=project.github_forks,
github_last_update=project.github_last_update,
github_last_commit=project.github_last_commit,
previous_urls=json.dumps(project.previous_urls),
)
def to_project(self) -> Project:
"""Convert ProjectDB back to Project."""
return Project(
name=self.name,
description=self.description,
url=self.url,
category=self.category,
slug=self.slug,
tags=json.loads(self.tags),
github_stars=self.github_stars,
github_forks=self.github_forks,
github_last_update=self.github_last_update,
github_last_commit=self.github_last_commit,
previous_urls=json.loads(self.previous_urls),
)
# Database configuration
DATABASE_PATH = Path("projects.db")
DATABASE_URL = f"sqlite:///{DATABASE_PATH}"
console = Console()
def get_engine():
"""Get SQLModel engine."""
return create_engine(DATABASE_URL, echo=False)
def init_db():
"""Initialize the database and create tables."""
engine = get_engine()
SQLModel.metadata.create_all(engine)
return engine
def parse_project_line(line: Tag, category: str) -> Project | None:
"""Parse a project line from the markdown and return a Project object."""
try:
# Find the project link
link = line.find("a")
if not link:
return None
name = link.text.strip()
url = link.get("href", "").strip()
# Get description (text after the link)
description = line.text.replace(name, "").strip()
description = re.sub(r"^\s*-\s*", "", description) # Remove leading dash
description = re.sub(r"^\s*", "", description) # Remove leading whitespace
if not all([name, url, description]):
return None
return Project(name=name, description=description, url=url, category=category)
except Exception as e:
print(f"[red]Error parsing project line: {e}[/red]")
return None
def read_readme(file_path: Path) -> str:
"""Read README content from local file and convert to HTML."""
markdown_content = file_path.read_text()
md = MarkdownIt()
html_content = md.render(markdown_content)
return html_content
def parse_readme(content: str) -> list[Project]:
"""Parse README content and extract projects."""
soup = BeautifulSoup(content, "html.parser")
projects = []
current_category = ""
for element in soup.find_all(["h2", "h3", "li"]):
if element.name in ["h2", "h3"]:
current_category = element.text.strip()
elif element.name == "li" and current_category:
if current_category == "Contents":
continue
project = parse_project_line(element, current_category)
if project:
projects.append(project)
return projects
def merge_project_data(existing: dict[str, Any], new: dict[str, Any]) -> dict[str, Any]:
"""
Merge existing project data with new data, preserving existing values
while updating with new information where appropriate.
"""
# Start with the existing data
merged = existing.copy()
# Always update core fields from the README
core_fields = {"name", "url", "category"}
for field in core_fields:
if field in new:
# If URL is changing, store the old URL in previous_urls
if field == "url" and new["url"] != existing.get("url"):
previous_urls = merged.get("previous_urls", [])
old_url = existing.get("url")
if old_url and old_url not in previous_urls:
previous_urls.append(old_url)
merged["previous_urls"] = previous_urls
merged[field] = new[field]
# Smart merge for description - update only if meaningfully different
if "description" in new and new["description"] != existing.get("description", ""):
merged["description"] = new["description"]
# Update GitHub metrics if they exist in new data
github_fields = {"github_stars", "github_forks", "github_last_update", "github_last_commit"}
for field in github_fields:
if field in new and new[field] is not None:
merged[field] = new[field]
return merged
def save_project(project: Project, output_dir: Path):
"""Save project as a markdown file with frontmatter, preserving and merging existing content."""
output_file = output_dir / f"{project.slug}.md"
project_data = project.model_dump(exclude_none=True)
if output_file.exists():
try:
# Load existing file
existing_post = frontmatter.load(output_file)
existing_data = dict(existing_post.metadata)
# Merge data, favoring preservation of existing content
merged_data = merge_project_data(existing_data, project_data)
# Create new post with merged data but keep existing content
post = frontmatter.Post(existing_post.content, **merged_data)
except Exception as e:
print(
f"[yellow]Warning: Could not load existing file {output_file}, creating new: {e}[/yellow]"
)
post = frontmatter.Post(project.description, **project_data)
else:
# Create new file
post = frontmatter.Post(project.description, **project_data)
output_file.write_text(frontmatter.dumps(post))
def extract_github_info(url: str) -> dict[str, str] | None:
"""Extract owner and repo from a GitHub URL."""
parsed = urlparse(url)
if parsed.netloc != "github.com":
return None
parts = parsed.path.strip("/").split("/")
if len(parts) >= 2:
return {"owner": parts[0], "repo": parts[1]}
return None
def get_github_metrics(
owner: str, repo: str, client: httpx.Client
) -> tuple[dict, str | None]:
"""
Fetch GitHub metrics for a repository.
Returns a tuple of (metrics_dict, new_url) where new_url is set if the repo has moved.
"""
headers = {}
if github_token := os.environ.get("GITHUB_TOKEN"):
headers["Authorization"] = f"token {github_token}"
api_url = f"https://api.github.com/repos/{owner}/{repo}"
try:
response = client.get(
api_url,
headers=headers,
timeout=10.0,
follow_redirects=True, # Enable following redirects
)
# Check if we followed a redirect
new_url = None
if len(response.history) > 0:
for r in response.history:
if r.status_code == 301:
# Get the new location from the API response
data = response.json()
new_url = data.get("html_url")
if new_url:
print(
f"[yellow]Repository moved: {owner}/{repo} -> {new_url}[/yellow]"
)
break
response.raise_for_status()
data = response.json()
metrics = {
"github_stars": data["stargazers_count"],
"github_forks": data["forks_count"],
"github_last_update": data["updated_at"],
}
# Fetch last commit date
commits_url = f"https://api.github.com/repos/{owner}/{repo}/commits"
try:
commits_response = client.get(
commits_url,
headers=headers,
params={"per_page": 1},
timeout=10.0,
follow_redirects=True,
)
commits_response.raise_for_status()
commits_data = commits_response.json()
if commits_data and len(commits_data) > 0:
metrics["github_last_commit"] = commits_data[0]["commit"]["committer"]["date"]
except httpx.HTTPError as e:
print(f"[yellow]Warning: Could not fetch commits for {owner}/{repo}: {str(e)}[/yellow]")
return metrics, new_url
except httpx.HTTPError as e:
print(f"[red]Error fetching GitHub metrics for {owner}/{repo}: {str(e)}[/red]")
return {}, None
def load_project(file_path: Path) -> Project | None:
"""Load a project from a markdown file."""
try:
post = frontmatter.load(file_path)
return Project(**post.metadata)
except Exception as e:
print(f"[red]Error loading project from {file_path}: {str(e)}[/red]")
return None
@app.command()
def parse(readme_path: Path = Path("README.md"), output_dir: str = "_projects"):
"""
Parse local Awesome Django README and create individual project files with frontmatter.
Preserves existing file content and metadata while updating with new information from README.
"""
if not readme_path.exists():
print(f"[red]Error: README file not found at {readme_path}[/red]")
raise typer.Exit(1)
print(f"[bold blue]Reading README from {readme_path}...[/bold blue]")
# Create output directory
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
# Read and parse README
content = read_readme(readme_path)
projects = parse_readme(content)
print(f"[green]Found {len(projects)} projects[/green]")
# Save individual project files
for project in projects:
save_project(project, output_path)
print(f"[green]Updated {project.name} in {project.slug}.md[/green]")
@app.command()
def update_metrics(projects_dir: Path = Path("_projects"), batch_size: int = 50):
"""
Update GitHub metrics (stars, forks, last update) for all projects.
"""
if not projects_dir.exists():
print(f"[red]Error: Projects directory not found at {projects_dir}[/red]")
raise typer.Exit(1)
print(
f"[bold blue]Updating GitHub metrics for projects in {projects_dir}...[/bold blue]"
)
# Load all projects
project_files = list(projects_dir.glob("*.md"))
projects = []
for file in project_files:
if project := load_project(file):
projects.append((file, project))
print(f"[green]Found {len(projects)} projects to update[/green]")
# Update metrics in batches to avoid rate limiting
with httpx.Client() as client:
for i in track(
range(0, len(projects), batch_size), description="Updating projects"
):
batch = projects[i : i + batch_size]
for file_path, project in batch:
if github_info := extract_github_info(project.url):
metrics, new_url = get_github_metrics(
github_info["owner"], github_info["repo"], client
)
if metrics:
# Update project with new metrics
for key, value in metrics.items():
setattr(project, key, value)
# Update URL if repository has moved
if new_url and new_url != project.url:
# Store the old URL in previous_urls
if not hasattr(project, "previous_urls"):
project.previous_urls = []
project.previous_urls.append(project.url)
# Update to new URL
project.url = new_url
print(
f"[yellow]Updated URL for {project.name}: {project.url}[/yellow]"
)
save_project(project, projects_dir)
print(f"[green]Updated metrics for {project.name}[/green]")
print("[bold blue]Finished updating GitHub metrics![/bold blue]")
@app.command()
def sync_db(projects_dir: Path = Path("_projects")):
"""
Sync projects from markdown files to SQLite database.
"""
if not projects_dir.exists():
print(f"[red]Error: Projects directory not found at {projects_dir}[/red]")
raise typer.Exit(1)
print(f"[bold blue]Syncing projects to {DATABASE_PATH}...[/bold blue]")
engine = init_db()
# Load all projects from markdown files
project_files = list(projects_dir.glob("*.md"))
projects_loaded = 0
with Session(engine) as session:
# Clear existing data
session.exec(select(ProjectDB)).all()
for existing in session.exec(select(ProjectDB)).all():
session.delete(existing)
session.commit()
# Load new data
for file in track(project_files, description="Loading projects"):
if project := load_project(file):
db_project = ProjectDB.from_project(project)
session.add(db_project)
projects_loaded += 1
session.commit()
print(f"[green]Synced {projects_loaded} projects to {DATABASE_PATH}[/green]")
@app.command()
def query(
category: Optional[str] = typer.Option(None, "--category", "-c", help="Filter by category"),
min_stars: Optional[int] = typer.Option(None, "--min-stars", "-s", help="Minimum GitHub stars"),
limit: int = typer.Option(20, "--limit", "-l", help="Maximum results to show"),
sort_by: str = typer.Option("stars", "--sort", help="Sort by: stars, name, commits"),
):
"""
Query projects from the database with filters.
"""
if not DATABASE_PATH.exists():
print("[red]Database not found. Run 'sync-db' first.[/red]")
raise typer.Exit(1)
engine = get_engine()
with Session(engine) as session:
statement = select(ProjectDB)
if category:
statement = statement.where(ProjectDB.category == category)
if min_stars:
statement = statement.where(ProjectDB.github_stars >= min_stars)
# Sorting
if sort_by == "stars":
statement = statement.order_by(ProjectDB.github_stars.desc())
elif sort_by == "name":
statement = statement.order_by(ProjectDB.name)
elif sort_by == "commits":
statement = statement.order_by(ProjectDB.github_last_commit.desc())
statement = statement.limit(limit)
results = session.exec(statement).all()
if not results:
print("[yellow]No projects found matching criteria.[/yellow]")
return
table = Table(title=f"Projects ({len(results)} results)")
table.add_column("Name", style="cyan", no_wrap=True)
table.add_column("Category", style="green")
table.add_column("Stars", justify="right", style="yellow")
table.add_column("Last Commit", style="magenta")
for p in results:
stars = str(p.github_stars) if p.github_stars else "-"
last_commit = p.github_last_commit[:10] if p.github_last_commit else "-"
table.add_row(p.name, p.category, stars, last_commit)
console.print(table)
@app.command()
def top(
limit: int = typer.Option(20, "--limit", "-l", help="Number of projects to show"),
category: Optional[str] = typer.Option(None, "--category", "-c", help="Filter by category"),
):
"""
Show top projects by GitHub stars.
"""
if not DATABASE_PATH.exists():
print("[red]Database not found. Run 'sync-db' first.[/red]")
raise typer.Exit(1)
engine = get_engine()
with Session(engine) as session:
statement = select(ProjectDB).where(ProjectDB.github_stars.isnot(None))
if category:
statement = statement.where(ProjectDB.category == category)
statement = statement.order_by(ProjectDB.github_stars.desc()).limit(limit)
results = session.exec(statement).all()
table = Table(title=f"Top {len(results)} Projects by Stars")
table.add_column("#", justify="right", style="dim")
table.add_column("Name", style="cyan", no_wrap=True)
table.add_column("Category", style="green")
table.add_column("Stars", justify="right", style="yellow")
table.add_column("Forks", justify="right", style="blue")
table.add_column("URL", style="dim")
for i, p in enumerate(results, 1):
table.add_row(
str(i),
p.name,
p.category,
f"{p.github_stars:,}",
str(p.github_forks or "-"),
p.url[:50] + "..." if len(p.url) > 50 else p.url,
)
console.print(table)
@app.command()
def categories():
"""
List all categories with project counts.
"""
if not DATABASE_PATH.exists():
print("[red]Database not found. Run 'sync-db' first.[/red]")
raise typer.Exit(1)
engine = get_engine()
with Session(engine) as session:
results = session.exec(select(ProjectDB)).all()
# Count by category
category_counts: dict[str, int] = {}
category_stars: dict[str, int] = {}
for p in results:
category_counts[p.category] = category_counts.get(p.category, 0) + 1
category_stars[p.category] = category_stars.get(p.category, 0) + (p.github_stars or 0)
# Sort by count
sorted_categories = sorted(category_counts.items(), key=lambda x: x[1], reverse=True)
table = Table(title="Categories")
table.add_column("Category", style="cyan")
table.add_column("Projects", justify="right", style="green")
table.add_column("Total Stars", justify="right", style="yellow")
for cat, count in sorted_categories:
table.add_row(cat, str(count), f"{category_stars[cat]:,}")
console.print(table)
print(f"\n[bold]Total: {len(sorted_categories)} categories, {len(results)} projects[/bold]")
@app.command()
def search(
query: str = typer.Argument(..., help="Search term"),
limit: int = typer.Option(20, "--limit", "-l", help="Maximum results"),
):
"""
Search projects by name or description.
"""
if not DATABASE_PATH.exists():
print("[red]Database not found. Run 'sync-db' first.[/red]")
raise typer.Exit(1)
engine = get_engine()
query_lower = query.lower()
with Session(engine) as session:
results = session.exec(select(ProjectDB)).all()
# Filter by search term
matches = [
p for p in results
if query_lower in p.name.lower() or query_lower in p.description.lower()
]
# Sort by stars
matches.sort(key=lambda x: x.github_stars or 0, reverse=True)
matches = matches[:limit]
if not matches:
print(f"[yellow]No projects found matching '{query}'[/yellow]")
return
table = Table(title=f"Search results for '{query}' ({len(matches)} matches)")
table.add_column("Name", style="cyan", no_wrap=True)
table.add_column("Category", style="green")
table.add_column("Stars", justify="right", style="yellow")
table.add_column("Description", style="dim", max_width=50)
for p in matches:
stars = str(p.github_stars) if p.github_stars else "-"
desc = p.description[:50] + "..." if len(p.description) > 50 else p.description
table.add_row(p.name, p.category, stars, desc)
console.print(table)
@app.command()
def stale(
days: int = typer.Option(365, "--days", "-d", help="Days since last commit to consider stale"),
limit: int = typer.Option(30, "--limit", "-l", help="Maximum results"),
):
"""
Find stale/unmaintained projects (no commits in X days).
"""
if not DATABASE_PATH.exists():
print("[red]Database not found. Run 'sync-db' first.[/red]")
raise typer.Exit(1)
engine = get_engine()
cutoff = datetime.now().replace(tzinfo=None)
with Session(engine) as session:
results = session.exec(
select(ProjectDB).where(ProjectDB.github_last_commit.isnot(None))
).all()
# Filter stale projects
stale_projects = []
for p in results:
try:
last_commit = datetime.fromisoformat(p.github_last_commit.replace("Z", "+00:00"))
last_commit = last_commit.replace(tzinfo=None)
days_since = (cutoff - last_commit).days
if days_since >= days:
stale_projects.append((p, days_since))
except (ValueError, AttributeError):
continue
# Sort by oldest first
stale_projects.sort(key=lambda x: x[1], reverse=True)
stale_projects = stale_projects[:limit]
if not stale_projects:
print(f"[green]No stale projects found (>{days} days without commits)[/green]")
return
table = Table(title=f"Stale Projects (no commits in {days}+ days)")
table.add_column("Name", style="cyan", no_wrap=True)
table.add_column("Category", style="green")
table.add_column("Stars", justify="right", style="yellow")
table.add_column("Last Commit", style="red")
table.add_column("Days Ago", justify="right", style="red")
for p, days_ago in stale_projects:
stars = str(p.github_stars) if p.github_stars else "-"
last_commit = p.github_last_commit[:10] if p.github_last_commit else "-"
table.add_row(p.name, p.category, stars, last_commit, str(days_ago))
console.print(table)
print(f"\n[bold red]Found {len(stale_projects)} stale projects[/bold red]")
@app.command()
def stats():
"""
Show database statistics.
"""
if not DATABASE_PATH.exists():
print("[red]Database not found. Run 'sync-db' first.[/red]")
raise typer.Exit(1)
engine = get_engine()
with Session(engine) as session:
all_projects = session.exec(select(ProjectDB)).all()
github_projects = [p for p in all_projects if p.github_stars is not None]
total_stars = sum(p.github_stars or 0 for p in all_projects)
categories = set(p.category for p in all_projects)
print("\n[bold blue]Database Statistics[/bold blue]")
print(f" Total projects: [green]{len(all_projects)}[/green]")
print(f" GitHub projects: [green]{len(github_projects)}[/green]")
print(f" Categories: [green]{len(categories)}[/green]")
print(f" Total stars: [yellow]{total_stars:,}[/yellow]")
if github_projects:
avg_stars = total_stars / len(github_projects)
max_stars_project = max(github_projects, key=lambda x: x.github_stars or 0)
print(f" Average stars: [yellow]{avg_stars:.0f}[/yellow]")
print(f" Most starred: [cyan]{max_stars_project.name}[/cyan] ({max_stars_project.github_stars:,} stars)")
if __name__ == "__main__":
app()