Django : le polymorphisme : astuces
Un excellent article écrit par Dan Bader (j’ai pas mal discuté avec lui et j’ai son livre, il est vraiment aussi bon que modeste, je vous recommande vivement tous ses articles – et n’hésitez pas à lui parler en Anglais (tant qu’il n’est pas encore trop connu !), il vous répondra sûrement).
Il manque juste ces « petits » détails techniques lorsqu’on se base sur les modèles abstraits et l’héritage au sens « modèle » de Django (Abstract Base Model).
Prenons un exemple simple : vous créez un modèle « simple » Media(models.Model)
dont vous allez hériter sur deux modèles : Book(Media)
et Dvd(Media)
.
Ce qui va vous prendre beaucoup de temps (et qui n’est expliqué nulle part de manière claire et directe), c’est que Django, de manière cachée, va créer des propriétés qui vont dans les deux sens entre le modèle parent et le modèle enfant.
Pour reprendre notre exemple, avec les trois modèles : Media
= parent, et les deux enfants Book
et Dvd
.
Imaginez que pour chaque enfant, vous créiez une méthode spécifique, par exemple Book.nb_pages()
et Dvd.is_blue_ray()
De manière cachée, vous pourrez à partir du parent, accéder à l’enfant et ses propriété via son nom comme ceci :
my_media = Media.object.get(pk=1)
if hasattr(self, 'book'): # this Media is a Book:
my_media.book.nb_pages()
elif hasattr(self, 'dvd'): # this media is a Dvd:
my_media.dvd.is_blue_ray()
else: # direct Media model access:
pass
A l’inverse, à partir des modèles enfants, pour accéder au parent c’est le nom du modèle parent avec _ptr
:
my_book = Book.object.get(pk=21)
my_dvd = Dvd.object.get(pk=75)
# imaginons que "price" est une propriété de Media
property. On peut écrire :
print(my_book.media_ptr.price)
print(my_dvd.media_ptr.price)