Guias por framework

Publicar Django na Zenifra

Este guia leva um projeto Django do repositório GitHub até produção, com arquivos estáticos, banco gerenciado e configurações seguras.

Pré-requisitos

  • Projeto Django em um repositório GitHub, com manage.py na raiz
  • requirements.txt com django, gunicorn, whitenoise e o driver do banco
  • Conta GitHub conectada à Zenifra
requirements.txt
Django==5.1.1
gunicorn==23.0.0
whitenoise==6.7.0
psycopg[binary]==3.2.2
dj-database-url==2.2.0

Os exemplos assumem que o pacote de configuração se chama config (config/settings.py, config/wsgi.py). Troque pelo nome do seu projeto.

Ajuste o settings.py

config/settings.py
import os
import dj_database_url

SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DJANGO_DEBUG", "false").lower() == "true"

ALLOWED_HOSTS = [".clients.zenifra.com"] + [
    h for h in os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",") if h
]
CSRF_TRUSTED_ORIGINS = ["https://*.clients.zenifra.com"] + [
    f"https://{h}" for h in os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",") if h
]

# A Zenifra encerra o HTTPS e informa o protocolo original neste header
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

DATABASES = {
    "default": dj_database_url.config(conn_max_age=600, conn_health_checks=True)
}

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",
    # ... demais middlewares
]

STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STORAGES = {
    "default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
    "staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"},
}

O WhiteNoiseMiddleware precisa vir logo depois do SecurityMiddleware.

Variáveis de ambiente

VariávelExemploPara quê
DJANGO_SECRET_KEYvalor aleatório longoAssinatura de sessões e tokens
DATABASE_URLpostgres://usuario:senha@host:5432/bancoConexão com o banco
DJANGO_ALLOWED_HOSTSapp.minhaempresa.com.brDomínios personalizados, separados por vírgula
DJANGO_DEBUGfalseNunca true em produção

Gere uma chave com python -c "import secrets; print(secrets.token_urlsafe(50))". As variáveis também existem durante a build, o que permite rodar collectstatic com o settings.py completo.

Configuração no console

CampoValor
RuntimePython 3.12
Porta8000
pre-buildvazio
buildpython manage.py collectstatic --noinput
startpython manage.py migrate --noinput && gunicorn config.wsgi --bind 0.0.0.0:8000 --workers 2 --access-logfile -

Por que migrate no start?

No start, a migration roda com acesso ao banco no ambiente final da aplicação, logo antes de o servidor subir. As migrations do Django usam transações no PostgreSQL, então uma falha não deixa o esquema pela metade.

Uploads de usuários (MEDIA)

Arquivos enviados por usuários não podem ficar no disco efêmero da instância. Escolha um caminho:

  • Armazenamento persistente com o diretório /app/media e MEDIA_ROOT = "/app/media". Para servir esses arquivos, use uma view própria ou um serviço de armazenamento de objetos.
  • Um serviço de armazenamento de objetos compatível com S3, com django-storages.

Tarefas assíncronas com Celery

Publique o worker do Celery como outro projeto, com o mesmo repositório e o start celery -A config worker --loglevel=info. Use o cache gerenciado ou as filas gerenciadas como broker.

Criar o superusuário

Defina DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_EMAIL e DJANGO_SUPERUSER_PASSWORD e adicione ao início do start, uma única vez:

python manage.py createsuperuser --noinput || true

Depois que o usuário existir, remova o comando e a variável com a senha.

Problemas comuns

SintomaCorreção
DisallowedHostInclua o domínio em ALLOWED_HOSTS ou em DJANGO_ALLOWED_HOSTS
CSRF verification failedInclua https://seu-dominio em CSRF_TRUSTED_ORIGINS
CSS e JS retornam 404collectstatic não rodou ou o WhiteNoise não está no MIDDLEWARE
Redirecionamento infinito com SECURE_SSL_REDIRECTConfigure SECURE_PROXY_SSL_HEADER como no exemplo
KeyError: 'DJANGO_SECRET_KEY' na buildCadastre a variável no projeto antes de publicar
too many connectionsReduza --workers ou conn_max_age; veja Problemas de conexão

Próximos passos

Última atualização em

Nessa página