django-countries

A Django model and form field for ISO 3166-1 country choices, with translated names and flag icons built in.

Library
PyPI
v9.0.0
1,531stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
57/100Fair
Development Activity40
Maintenance28
Community72
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture82
Code Quality90
Innovation78
Learning Curve80

django-countries is a Django application that adds a CountryField for models and forms, backed by the full ISO 3166-1 country list. Rather than hand-rolling a CharField with a giant choices= tuple, it gives you a drop-in field whose values behave like rich Country objects — comparable to plain codes, but carrying a translated display name and a static flag icon URL for free.

Beyond the core field, the package covers the integrations a real project needs around country data: Django REST Framework serializer fields, GraphQL types for graphene-django, django-filter support for queryset filtering, multi-select country fields, and pluggable custom country lists via setuptools entry points. Country names are translated through Django’s standard gettext machinery, sourced from an actively maintained Transifex project.

What You Get

  • A CountryField for Django models storing the ISO alpha-2 code with full form/admin integration
  • Rich Country objects with translated names, alpha-3/numeric/IOC codes, and flag URLs
  • Static flag icon assets for every ISO 3166-1 country, served through Django’s static files
  • Django REST Framework serializer fields and graphene-django GraphQL type support
  • django-filter integration for filtering querysets by country
  • Support for multi-select country fields and custom/extended country lists via entry points

Common Use Cases

  • Adding a country selector to a user profile or address model without hand-maintaining a choices list
  • Rendering a translated country name and flag in templates for an internationalized site
  • Exposing country fields through a DRF API or GraphQL schema in a consistent, typed way
  • Filtering an admin changelist or queryset by country using django-filter
  • Building shipping/billing forms that need ISO-compliant country codes for downstream integrations

Under The Hood

Architecture The package centers on fields.py, where CountryField subclasses Django’s CharField and overrides value conversion so reads/writes pass through the Country wrapper defined in __init__.py; Countries/countries (in base.py and __init__.py) own the ISO dataset in data.py and expose lookups by alpha-2/alpha-3/numeric/IOC code, with conf.py bridging Django settings for overrides. Peripheral concerns are cleanly separated into their own modules: widgets.py for the form widget and flag-changing JS hook, serializers.py/serializer_fields.py for DRF, a graphql/ subpackage for graphene-django types, and django_filters.py/filters.py for queryset filtering — each is optional and only imported if the consuming project uses that integration, so the core field has no hard dependency on DRF or GraphQL being installed.

Tech Stack The library targets modern Django (4.2 LTS through 6.0) and Python 3.10-3.14, declaring only asgiref and typing_extensions as hard runtime dependencies, with pyuca as an optional extra for locale-aware sorting. It builds with uv_build rather than setuptools, and its dev/test tooling (declared in pyproject.toml dependency groups) spans pytest/pytest-django/pytest-cov, ruff, mypy with django-stubs, bandit, and towncrier for changelog management, orchestrated through a justfile rather than raw tox or make.

Code Quality The django_countries/tests/ directory holds a comprehensive suite covering fields, admin display, admin filters, DRF serialization, GraphQL, widgets, template tags, settings, and null-handling, run across a CI matrix of legacy/previous/latest Python-Django combinations plus pyuca and no-i18n variants. The package ships a py.typed marker and a hand-written fields.pyi stub alongside mypy configured with disallow_untyped_calls and the Django mypy plugin, giving it a stricter type-checking posture than most Django add-ons; a dedicated lint-and-type-check CI job runs ruff and mypy on every push.

API Design CountryField is designed to be a near drop-in replacement for a plain CharField/choices setup, so existing model code migrates with minimal changes, while the returned Country objects layer in __eq__/__str__/__bool__ so they compare and render naturally against plain string codes without extra unwrapping. Extensibility is opt-in via setuptools entry points (django_countries.Country) rather than subclassing requirements, and optional integrations (DRF, GraphQL, django-filter) are additive modules a project only touches if it needs them, keeping the base API surface small.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search