Mais algumas coisas sobre Django que tenho gostado
Olá! Estou em uma jornada engraçada agora, onde estou tentando aprender como fazer sites no estilo 2010, onde tenho um banco de dados SQL e renderizo algum HTML no backend.
É uma jornada interessante porque não parece necessariamente “fácil” para mim fazer sites desta forma: nunca aprendi como fazer isso nos anos 2000 ou 2010, e há muito que preciso aprender.
Então, aqui estão alguns recursos do Django que fazem com que a construção desse tipo de site pareça mais viável do que quando eu estava tentando e não consegui usar a biblioteca padrão do Go ou o Flask. E falarei sobre alguns problemas que encontrei com o Django.
por que aprender a fazer sites como em 2010?
Anteriormente, o kit de ferramentas com o qual me sentia confiante para criar sites era:
- geradores de sites estáticos (como neste blog)
- sites estáticos que fazem coisas divertidas com Javascript (como este playground sql)
- aplicativos simples de página única Vue.js com Lambda como back-end ou back-end Go (como mexer com DNS)
Eu realmente gostei dessa abordagem pesada de frontend para esses aplicativos super simples, mas quando comecei a pensar em fazer algo com muitas páginas diferentes (em vez de literalmente apenas uma página), não fiquei tão animado com as opções que vi que envolviam muito código de frontend. Então pensei em tentar o back-end.
Escrever um site focado em back-end que use o mínimo de JS possível parece o mesmo para mim, da mesma forma que escrever um site JS de página única que faça o mínimo possível de back-end, mesmo que possam parecer opostos. Em ambos os casos, estou apenas tentando manter o máximo possível de lógica em um só lugar.
Agora, algumas reflexões sobre Django!
Estou gostando dos construtores de consultas
Aprendi que posso definir uma classe de “conjunto de consultas” no Django com vários métodos com diferentes WHERE declarações que talvez eu queira usar ao construir uma consulta:
Veja como eu o uso em meu código de visualização depois de definir o que todos os métodos significam:
Events.objects.approved()
.for_tab(tab)
.with_festivals(tab_params.festival_slugs)
.is_free(tab_params.free)
.is_outdoors(tab_params.outdoors)
e aqui está como eu defino os métodos:
class EventQuerySet(SearchableQuerySetMixin, models.QuerySet):
def approved(self):
return self.filter(approved_at__isnull=False)
def future(self):
today = timezone.localdate()
return self.filter(end__gt=self._midnight(today))
def with_tags(self, tags):
if tags:
return self.filter(tags__name__in=tags).distinct()
return self
A sintaxe para definir os filtros não é minha favorita, mas passo a maior parte do tempo apenas usando os métodos, e parece super legível e agradável de usar, e isso me faz querer procurar outras bibliotecas de construtores de consultas no futuro. No passado eu pensava “Eu conheço SQL, quem precisa de um construtor de consultas?”, mas esse tipo de estrutura torna a leitura muito agradável.
Encontrei um exemplo de alguém que escreveu seu próprio pequeno construtor de consultas em Python que quero ler mais tarde para pensar se gostaria de usar uma versão mais minimalista dele.
os filtros de modelo são incríveis
Existem vários filtros de qualidade de vida disponíveis nos modelos do Django que são muito úteis para gerar HTML. Os que usei até agora são:
- traduzir URLs de texto simples em links ou quebras de linha em
({{ event.description|urlize|linebreaksbr }}) - formatação de datas (
{{ row.date|date:"M j" }}) json_scriptque pega um dicionário Python e o converte automaticamente em JSON e o insere no HTML como ummarque de forma segura
Todas essas coisas são pequenas individualmente, mas sinto que faz uma grande diferença apenas tê-las disponíveis.
querystring é legal
Acho que meu filtro de modelo favorito é querystring: neste site às vezes usamos filtros como ?date=2026-06-01 para decidir o que será exibido. querystring
isso criará um link para a mesma string de consulta com uma alteração, como esta para vincular à data anterior:
Ou para remover o outdoors parâmetro:
migrações automáticas de banco de dados ainda são ótimas
Eu ainda adoro o sistema de banco de dados automático do Django. É incrível poder simplesmente editar um modelo para adicionar um novo campo ou algo assim, e então o Django gera automaticamente a migração.
Até agora fizemos 19 migrações de banco de dados e acho que provavelmente haverá mais! Faz uma grande diferença para mim poder alterar facilmente o banco de dados à medida que minha compreensão do problema muda.
Não quero organizar meu código com herança
A documentação do Django às vezes oferece a opção de usar visualizações e herança baseadas em classes para organizar o código em suas visualizações. Por exemplo, tenho quatro visualizações que compartilham muito código e poderia usar herança para gerenciar isso, definindo algum tipo de classe pai e fazendo com que minhas outras visualizações herdem dela.
Eu experimentei e não gostei da experiência de usar herança para compartilhar código entre visualizações. Em vez disso, mudei para o uso de funções, mais ou menos como este post defende, e isso foi muito mais direto. Nunca tive uma boa experiência usando herança em Python e acho que não tentarei usá-la novamente.
Mas não me importo de usar herança para usar as interfaces que o próprio Django fornece: por exemplo, se eu quiser definir um conjunto de consultas, preciso escrever algo como
class EventQuerySet(SearchableQuerySetMixin, models.QuerySet). Não penso muito sobre isso e parece funcionar.
(como um meta-comentário: tenho trabalhado para falar sobre minhas opiniões de programação apenas dizendo “COISA não parece bom para mim, prefiro OUTRA COISA”. Aquele post ao qual vinculei diz que visualizações baseadas em função são o “caminho certo”. Não estou muito empenhado em saber se é “certo”, mas é uma validação saber que outras pessoas pensam da mesma forma que eu sobre herança)
Não sei como pensar no desempenho do Django
Em algum momento, os raspadores do LLM descobriram nosso site e começaram a nos enviar cerca de 10 solicitações por segundo. Bloqueei o que está funcionando por enquanto, mas me fez pensar qual é a capacidade do site. Estou acostumado a escrever back-ends Go onde a situação de desempenho é bastante direta (geralmente tudo é rápido o suficiente) e um site Django é muito diferente.
Alguns testes de carga leve (com (ab -n 1000 -c 1) mostra que no momento podemos atender cerca de 2 a 3 solicitações por segundo (em uma VM de aproximadamente US$ 10/mês).
É tentador para mim entrar na toca do coelho, onde faço vários perfis para descobrir o que é lento e tentar torná-lo mais rápido (há o py-spy para isso, e o py-spy é ótimo e super fácil de usar, e criar perfis é divertido!) Mas eu realmente não entendo o que devo esperar em termos de desempenho de um site Django e como devo pensar em um nível superior.
Algumas coisas que ainda não descobri:
- Se eu tiver um site que receberá picos ocasionais de tráfego, quero poder aumentá-lo?
- Quero projetar o site para que mais coisas possam ser armazenadas em cache? (e eu realmente preciso? Os caches são tão chatos de acertar!)
- Os documentos de desempenho do Django dizem que Jinja é mais rápido para modelagem, quero pensar em mudar de sistema de modelagem?
- Esses documentos também dizem que “{% block %} é mais rápido do que usar {% include %}”, eu me pergunto se é uma grande diferença e se sim, por que
o cache do modelo pode ser importante
Acho que uma coisa que estou aprendendo sobre o Django é que, por ser um Framework ™, é fácil configurá-lo incorretamente acidentalmente. Por exemplo, quando eu estava pensando por que meu site estava lento agora, li a documentação de desempenho do Django e notei um comentário dizendo:
Habilitar o carregador de modelos em cache geralmente melhora drasticamente o desempenho, pois evita a compilação de cada modelo toda vez que ele precisa ser renderizado.
Quando fiz o perfil da CPU, percebi que estava gastando muito tempo renderizando modelos! Talvez isso possa me ajudar!
Clicando no link, vi que o carregador de modelos em cache deveria estar ativado por padrão, mas eu o desliguei acidentalmente enquanto tentava fazer outra coisa. Eu acho que essa coisa de “desativei o carregador de modelos em cache por padrão” é um exemplo de como ainda acho o arquivo de configurações do Django bastante confuso e difícil. Acho que devo ter cuidado ao entrar lá.
Depois de ativar o cache de modelos, parece que o site agora pode lidar facilmente com cerca de 12 solicitações por segundo, sem usar toda a CPU. Não comparei cuidadosamente o antes e o depois, mas parece que fez uma grande diferença.
Uma coisa que tem me surpreendido sobre o desempenho do Django é que sempre ouvi o conselho “se você tiver um problema de desempenho, verifique suas consultas ao banco de dados! Talvez adicione um índice!”. Mas tenho enfrentado vários problemas de desempenho (como esse problema de cache de modelo) que não são devido a consultas lentas; portanto, até agora, tem sido mais útil para mim começar executando um perfil de CPU. E como estou usando o SQLite, qualquer problema de consulta lenta ao banco de dados aparecerá no perfil da CPU de qualquer maneira.
De qualquer forma, não quero me aprofundar muito no desempenho do site. Como eu disse, é fácil me interessar por criação de perfil, mas na verdade eu sei muito sobre criação de perfil e não é a coisa mais importante para eu aprender.
isso é tudo por agora!
Posso dizer mais sobre o que estou gostando (ou tendo dificuldades!) no Django mais tarde. Tentando escrever algumas postagens mais curtas no blog recentemente.






