Arruda

Um Blog Sobre Tecnologia, Informação, Literatura e Coisas da Vida

Django - Herança, Modelos Abstratos e OO Na Veia


Uma coisa que percebi a algum tempo, é que existem poucas referencias à isso nos tutoriais de modo geral, e que usar os conceitos de OO em Django ajudam, e muito, quando seus módulos começam a ficar meio "repetido".
Felizmente depois de começar a trabalhar na SparkIt, meu colega Victor Fontes me deu umas dicas de como fazer isso sem problemas. E gostaria de compartilhar isso com vocês.

Herança

Segue a um cenario de exemplo: No exemplo a seguir vemos duas classes, A e B que tem um campo em comum: Nome. **Problemas:**

  • Rescrever Codigo:
  • Manutenção:

Então vemos de cara que podemos usar o conceito mais basico de OO: Herança. Vamos criar uma classe pai C que ira **Generalizar** A e B: **Vantagens:**

  • Reutilização de Codigo:
  • Manutenção:

Problemas:
Os models são classes que são persistidas em bancos de dados, correto?
Aí, entra o problema.

No banco de dados as tabelas ficaram(mais ou menos) da seguinte forma:
A(id_c,atributo_a)
B(id_c,atributo_b)
C(id, nome)

Isso é, se fizermos uma consulta:
A.objects.get(nome="Arruda")
O django ira fazer um Join de A + C para poder pegar o atributo Nome de A.
E isso irá fazer com que suas consultas mais simples se tornem muito pesadas.(Imagine um join numa tabela C que tem os nomes de todos os dados de 20 classes diferentes... é bastante coisa né).
Logo ficamos desencorajados a usar Herança como deve ser usada.

Mas, existe uma solução:

Modelos Abstratos

No Django é possivel definir um model como sendo abstrato, isso é: **Não é persistido no banco de dados.** O exemplo anterior ficaria da seguinte forma(fazendo a **classe C como Abstrata**): **Vantagens:**

  • Sem Joins:
  • Além de todas as vantagens de usar Herança.

Isso é algo que permite uma grande variadade de coisas, ainda mais quando usamos Herança Múltipla.

Herança Múltipla

Vamos incrementar o exemplo, vamos supor que tanto A quanto B tenham chave estrangeira para uma classe D. Com isso podemos criar uma classe F que faca essa ligação: Com isso, nossas classes A e B ambas tem os campos Nome e uma chave estrangeira para D.

**Mas pera ai!** E se eu quiser definir um related\_name? Nesse caso fazemos um pequeno ajuste na classe F: Com essa alteração fazemos com que de **F** possamos **acessar B** da seguinte forma:

Um abraço, e desejo a todos:
Que todos tenham prósperos projeto,
Que seus testes funcionem,
Que programem bastante e se divirtam nessas ferias.

Ah sim, e um feliz ano novo e feliz natal... essas trivialidades de sempre...