Skip to main content

Leia em Português

django-edne-cep

PyPI version CI Coverage

Enables CEP (Código de Endereçamento Postal, Brazilian postal code) lookups in your Django app backed by a local database. Uses edne-correios-loader to populate the database from Correios eDNE data, eliminating any dependency on external APIs.

  • Local database lookups, no external API calls, no network latency
  • Cache with stampede protection (sentinel-based, caches not-found results too)
  • Form field with CEP format validation and automatic address lookup
  • Django admin integration (opt-in)
  • Configurable table names, database alias, and cache backend

CEP Lookup Demo

HTMX-powered CEP lookup in the example app

Admin Integration

Django admin showing CEP data

Quick Start

Step 1: Install

pip install django-edne-cep

Step 2: Add to INSTALLED_APPS

INSTALLED_APPS = [
    ...
    "django_edne_cep",
]

Step 3: Load CEP data

python manage.py load_edne_cep --auto-download

This downloads the eDNE dataset from Correios (~350 MB) and populates the local database. Subsequent runs reuse the cached file.

Use it:

from django_edne_cep import lookup_cep

cep = lookup_cep("01310-100")
if cep:
    print(f"{cep.logradouro}, {cep.municipio}/{cep.uf}")
    # "Avenida Paulista, São Paulo/SP"

API Reference

def lookup_cep(cep_str: str) -> Cep | None

Look up a CEP in the local database. Accepts both "01310-100" and "01310100" formats.

  • Raises ValidationError for malformed input (not a valid CEP format).
  • Returns None when the CEP is not found in the database (valid format, not in eDNE data).
  • Results are cached using the configured cache backend.
from django_edne_cep import lookup_cep
from django.core.exceptions import ValidationError

cep = lookup_cep("01310-100")   # accepts "01310-100" or "01310100"
if cep:
    print(f"{cep.logradouro}, {cep.municipio}/{cep.uf}")

try:
    lookup_cep("ABC")           # raises ValidationError for malformed input
except ValidationError:
    pass

The returned Cep instance has the following fields:

cep.cep                # "01310100"  (8 digits, no hyphen)
cep.cep_formatado      # "01310-100" (property)
cep.logradouro         # str | None
cep.complemento        # str | None
cep.bairro             # str | None
cep.municipio          # str
cep.municipio_cod_ibge # int
cep.uf                 # str (2 chars, e.g. "SP")
cep.nome               # str | None
cep.as_dict()          # dict with all fields above

CepFormField

A CharField subclass that validates CEP format and returns a Cep instance from clean().

  • Accepts "00000000" or "00000-000" input formats.
  • Raises ValidationError with code "cep_not_found" when the CEP is not in the database.
  • form.cleaned_data["cep"] is a Cep instance, not a string.
from django import forms
from django_edne_cep import CepFormField

class EnderecoForm(forms.Form):
    cep = CepFormField()
    logradouro = forms.CharField(required=False)
    municipio = forms.CharField(required=False)

# In a view:
form = EnderecoForm(request.POST)
if form.is_valid():
    cep_obj = form.cleaned_data["cep"]  # Cep instance
    print(cep_obj.logradouro, cep_obj.municipio, cep_obj.uf)

validate_cep_format

A Django RegexValidator that accepts "00000000" and "00000-000" formats. Raises ValidationError with code "invalid_cep_format" on failure.

from django_edne_cep import validate_cep_format

validate_cep_format("01310-100")   # passes silently
validate_cep_format("01310100")    # passes silently
validate_cep_format("ABC")         # raises ValidationError

Use it directly on any CharField or Field that should accept CEP values without triggering a database lookup.


register_admin(site: AdminSite | None = None) -> None

Registers the Cep model with a read-only CepAdmin in the given admin site. The standard use case requires no manual call. Set EDNE_CEP["ADMIN_ENABLED"] = True in Django settings instead.

register_admin() is called automatically when django_edne_cep.admin is imported with ADMIN_ENABLED=True. The explicit call is only needed for a custom AdminSite.

# Standard usage, set in Django settings:
EDNE_CEP = {
    "ADMIN_ENABLED": True,
}

# Custom AdminSite usage only:
from django_edne_cep import register_admin
register_admin(site=my_custom_site)

Configuration

All settings go in the EDNE_CEP dict in your Django settings file:

EDNE_CEP = {
    "CACHE_TIMEOUT": 7200,
    "ADMIN_ENABLED": True,
}
Setting Type Default Description
TABLE_NAMES dict see below Override individual eDNE table names
TABLE_SET str | None None Load only a subset of tables (e.g. "cep")
EDNE_SOURCE str | None None Path or URL to eDNE zip file; None prompts download
DATABASE_ALIAS str "default" Django database alias for CEP tables
DATABASE_URL str | None None Direct database URL (overrides DATABASE_ALIAS)
CACHE_TIMEOUT int 3600 Cache TTL in seconds; 0 disables cache
CACHE_ALIAS str "default" Django cache alias for CEP lookups
ADMIN_ENABLED bool False Register CEP models in Django admin

Default TABLE_NAMES:

TABLE_NAMES = {
    "cep_unificado": "edne_cep",
    "log_localidade": "edne_localidade",
    "log_bairro": "edne_bairro",
    "log_cpc": "edne_caixa_postal",
    "log_logradouro": "edne_logradouro",
    "log_grande_usuario": "edne_grande_usuario",
    "log_unid_oper": "edne_unidade_operacional",
}

Override individual entries to map eDNE table names to your own table names.

Admin

Enable the read-only Django admin for CEP data:

# settings.py
EDNE_CEP = {
    "ADMIN_ENABLED": True,
}

The CepAdmin registers automatically when django_edne_cep.admin is imported. It supports full-text search by CEP, street name, neighborhood, and municipality, plus filters by state (UF) and field presence.

For a custom AdminSite, call register_admin(site=my_site) explicitly after setting ADMIN_ENABLED = True.

Admin Integration

Example App

The example/ directory contains a standalone Django project with an HTMX-powered CEP autofill form: type a CEP and the address fields fill in automatically without a page reload.

See example/README.md for full instructions on running it locally.

License

MIT

Metadata

Release files for django-edne-cep 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-edne-cep 0.1.0
File Size Uploaded
django_edne_cep-0.1.0.tar.gz 12.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-edne-cep 0.1.0
File Interpreter ABI Platform
django_edne_cep-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 29.1 kB

Release files / django_edne_cep-0.1.0.tar.gz

Download URL django_edne_cep-0.1.0.tar.gz
Size 12.3 kB
Tags Source
SHA-256 checksum
How to use checksums
fadf09b7beeea745c5b9650b8f41484f658d3cde22170803529608a2da646250
BLAKE2b-256 checksum
How to use checksums
b4ab27b09e9fd7aa330b9044ff0f59f8eb27b2a36995efdb35017eafe9b3daa4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / django_edne_cep-0.1.0-py3-none-any.whl

Download URL django_edne_cep-0.1.0-py3-none-any.whl
Size 16.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
17b9a98844050bb8d803775b7f2057e71d6828c3b1d6992e7da91006bc4e974b
BLAKE2b-256 checksum
How to use checksums
c0617cd999dab341007965eaf632784eba58cc14663b6fcddd1b05f3f01fa292
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page