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:
      Como pode se perceber você acaba reescrevendo codigo que nem um louco(imagine se fossem 10 classes e todas tivessem um atributo Nome!)
  • Manutenção:
      Imagina se você decide mudar o campo nome pra que ele tenha max_length=100, teria que sair alterando todas as classes.

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:
      Você escreve uma classe que possui o(s) campo(s) genéricos e depois herda dessas classes. Não tem que sair escrevendo campos/métodos em varias classes.
  • Manutenção:
      Mudar o campo nome pra que ele tenha max_length=100 seria necessário apenas mudar o atributo na classe C.

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:
      Diferente de quando fizemos com uma classe normal, ao usar uma abstrata todos os campos de C são criados nas tabelas que herdam do mesmo.
  • 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…

About arruda

Adoro programar, descobrir novas frameworks ágeis e suas diversas aplicações.