O urls.py do Django é o ponto onde muitos projetos quebram no início.
Na prática, o erro acontece quando as rotas crescem e ninguém entende mais quem responde o quê.
Neste artigo, explico como o urls.py funciona, como organizar rotas, usar include, lidar com mídia, sitemap e SEO.
Ao final, você consegue ler um urls.py real sem medo e ajustar o seu com segurança.

O papel do urls.py no projeto Django

O urls.py é o roteador do Django.
Toda requisição HTTP passa por ele antes de chegar em uma view.

O fluxo real é este:

  1. O usuário acessa uma URL no navegador

  2. O Django compara essa URL com urlpatterns

  3. A primeira rota compatível é executada

  4. A view associada retorna a resposta

Se não houver correspondência, o famoso 404 aparece.

Na prática, o urls.py conecta:

  • URLs → views

  • URLs → apps

  • URLs → arquivos estáticos auxiliares (sitemap, robots)

Sem esse arquivo bem definido, o projeto até roda, mas não responde corretamente.

Estrutura básica de um urls.py funcional

Um urls.py real raramente é minimalista.
Este é um exemplo próximo do que uso em produção:

 
from django.contrib import admin from django.urls import path, include from django.conf import settings from django.conf.urls.static import static from django.contrib.sitemaps.views import sitemap from django.views.generic import TemplateView from blog.sitemaps import PostSitemap, CategorySitemap

Aqui acontece muita coisa importante:

  • path: define rotas

  • include: delega rotas para outros apps

  • settings e static: servem mídia em desenvolvimento

  • sitemap: expõe o sitemap.xml

  • TemplateView: serve arquivos simples, como robots.txt

Nada disso é teórico. Todos esses imports aparecem quando o projeto cresce.

Entendendo urlpatterns na prática

O coração do urls.py é a lista urlpatterns.

 
urlpatterns = [ path("admin/", admin.site.urls), path("", include("blog.urls")), path("", include("pages.urls")), ]

O que observei na prática:

  • A ordem importa

  • O Django testa as rotas de cima para baixo

  • A primeira que bater é usada

O admin/ é explícito.
Já os include delegam a responsabilidade para cada app.

Isso evita um erro comum: um único arquivo gigante com todas as rotas do projeto.

Cada app controla suas próprias URLs, e o projeto principal só conecta tudo.

Usando include para manter o projeto organizado

Sempre que um app cresce, ele deve ter seu próprio urls.py.

Exemplo no app blog:

 
from django.urls import path from . import views urlpatterns = [ path("", views.post_list, name="post_list"), path("<slug:slug>/", views.post_detail, name="post_detail"), ]

No projeto principal, você só conecta:

 
path("", include("blog.urls")),

Esse padrão evita conflitos, melhora leitura e facilita manutenção.
Testei isso em projetos pequenos e grandes. Sempre vale a pena.

O que é programar na prática?

Entenda como a programação funciona no dia a dia, o que realmente significa programar e como isso se aplica fora da teoria.

Entender como programar

Configuração de arquivos de mídia no urls.py

Durante o desenvolvimento, imagens e uploads não aparecem sem essa configuração.

 
if settings.DEBUG: urlpatterns += static( settings.MEDIA_URL, document_root=settings.MEDIA_ROOT, )

Na prática, o erro acontece quando:

  • O upload funciona

  • O arquivo existe

  • Mas o navegador retorna 404

Esse bloco resolve isso apenas em desenvolvimento.

Em produção:

  • Use Nginx

  • Use CDN

  • Nunca sirva mídia via Django diretamente

Sitemap no urls.py e impacto em SEO

O Django tem suporte nativo a sitemap.
Isso economiza muito tempo.

Primeiro, você define os sitemaps:

 
sitemaps = { "posts": PostSitemap, "categories": CategorySitemap, }

Depois, expõe a URL:

 
urlpatterns += [ path( "sitemap.xml", sitemap, {"sitemaps": sitemaps}, name="django.contrib.sitemaps.views.sitemap", ), ]

Na prática, isso gera:

  • URLs automáticas

  • Datas de atualização

  • Prioridade de rastreamento

Para sites com blog ou conteúdo indexável, isso é obrigatório.

Cache no sitemap para evitar desperdício

O sitemap não muda a cada requisição.
Cachear é uma decisão óbvia.

 
from django.views.decorators.cache import cache_page path( "sitemap.xml", cache_page(60 * 60)(sitemap), {"sitemaps": sitemaps}, ),

Esse ajuste simples reduz carga e melhora resposta.
Testei isso em projetos com tráfego real. Funciona bem.

Float em Python: guia prático com exemplos

Se você já entendeu variáveis, aplique o conceito com números decimais. Leia o guia prático sobre float em Python, com exemplos reais e erros comuns:

Entender float em Python

Servindo robots.txt pelo urls.py

Organização de URLs no Django usando urls.py
Exemplo de organização de URLs em um projeto Django profissional.

Você não precisa de uma view só para robots.txt.

 
urlpatterns += [ path( "robots.txt", TemplateView.as_view( template_name="robots.txt", content_type="text/plain", ), ), ]

Com isso:

  • O arquivo fica em templates/robots.txt

  • O Django entrega como texto puro

  • Não há lógica desnecessária

Esse padrão é simples, limpo e eficiente.

Boas práticas que evitam problemas reais

Depois de quebrar alguns projetos, estas regras ficaram claras:

Separe responsabilidades

  • Projeto conecta apps

  • App define suas próprias rotas

Evite URLs duplicadas

Duas rotas parecidas causam bugs difíceis de rastrear.

Nomeie rotas corretamente

Use name sempre.
Você vai agradecer ao usar reverse() ou {% url %}.

Não exagere no urls.py principal

Se ficou grande demais, algo está errado.

Revise após cada feature nova

Rotas esquecidas geram comportamento inesperado.

Conclusão

O urls.py do Django não é só configuração.
Ele define como o projeto responde ao mundo.

Neste artigo, vimos:

  • Como o Django resolve URLs

  • Como usar include corretamente

  • Como servir mídia em desenvolvimento

  • Como expor sitemap e robots

  • Boas práticas que evitam bugs reais

Se o seu projeto está crescendo, revisar o urls.py é um dos ajustes mais seguros que você pode fazer.
Aplique os padrões apresentados e mantenha o controle da navegação.