2009-10-17 11 views
5

Mam modeluDziedziczenie Django: jak uzyskać jedną metodę dla wszystkich podklas?

BaseModel 

i kilka podklas nim

ChildModelA(BaseModel), ChildModelB(BaseModel), ... 

za pomocą multi-table dziedziczenia. W przyszłości planuję mieć dziesiątki modeli podklas.

Wszystkie podklasy pewne wdrożenie metody

do_something() 

Jak mogę zadzwonić do_somthing z instancji BaseModel?

Niemal identyczny problem (bez rozwiązania) jest zamieszczona tutaj:
http://peterbraden.co.uk/article/django-inheritance

Prostsza pytanie: w jaki sposób mogę rozwiązać BaseModel instnace do jednego z jej instancji podklasy bez sprawdzenia wszystkich możliwych podklasy?

Odpowiedz

1

Czy kiedykolwiek będziesz pracować z instancją typu podstawowego lub zawsze będziesz pracować z instancjami dzieci? Jeśli tak jest, wywołaj metodę, nawet jeśli masz odniesienie do typu podstawowego, ponieważ sam obiekt jest typu potomnego IS-A.

Ponieważ obsługa Pythona duck typing oznacza to, że twoje wywołanie metody będzie odpowiednio powiązane, ponieważ instancja podrzędna naprawdę będzie miała tę metodę.

pythonic styl programowania, który określa rodzaj obiektu, przez inspekcji jej metody lub atrybut podpisem zamiast za wyraźną stosunku do jakiegoś obiektu typu („Jeśli wygląda jak kaczka i kwacze jak kaczkę, to musi być kaczka. ") Przez kładąc nacisk na interfejsy, a nie na konkretne typy , dobrze zaprojektowany kod poprawia elastyczność, umożliwiając polimorficzne podstawienie . Kaczka-pisząc unika testów używając type() lub isinstance(). (Należy jednak pamiętać, że typowanie kaczek można uzupełnić o abstrakcyjne klasy bazowe . Zamiast tego, zwykle stosuje testy hasattr() lub programowanie EAFP.

Zauważ, że stoi EAFP dla Easier to Ask Forgiveness than Permission:

Łatwiej prosić o przebaczenie niż pozwolenie. Ten wspólny styl kodowania Python zakłada istnienie ważnych kluczy lub atrybutów i wyjątków odłowu, jeśli założenie okaże się fałszywe. Ten czysty i szybki styl charakteryzuje się obecnością wielu instrukcji try i except. Technika kontrastuje z stylem LBYL wspólnym dla wielu innych języków, takich jak C.

+1

Wszystko to jest poprawne, ale nie ma znaczenia w tym przypadku. Problem polega właśnie na tym, że podczas pracy z dziedziczeniem wielowarstwowym Django często występuje instancja klasy podstawowej (np. Z zapytania do tabeli podstawowej), nawet jeśli obiekt jest "naprawdę" typu podrzędnego (tzn. wpis w tabeli podrzędnej). –

0

Zgadzam się z Andrew. Na kilku stronach mamy klasę, która obsługuje całą masę metod (ale nie pól (to był refactor ORM)), które są wspólne dla większości, ale nie wszystkich naszych klas treści. Korzystają z hasattr do omijania sytuacji, w których metoda nie ma sensu.

Oznacza to większość naszych zajęć są określone jako:

class Foo(models.Model, OurKitchenSinkClass): 

Zasadniczo jest to rodzaj wstawek typu rzeczy. Działa świetnie, jest łatwy w utrzymaniu.

2

Jeśli chcesz uniknąć sprawdzania wszystkich możliwych podklas, jedyny sposób, jaki mogę wymyślić, to zapisanie nazwy klasy związanej z podklasą w polu zdefiniowanym w klasie bazowej. Klasa bazowa może mieć metody takie jak to:

def resolve(self): 
    module, cls_name = self.class_name.rsplit(".",1) 
    module = import_module(module) 
    cls = getattr(module, cls_name) 
    return cls.objects.get(pk=self.pk) 

Ta odpowiedź nie czyni mnie szczęśliwym i ja też chciałbym zobaczyć lepsze rozwiązanie, jak będę mieć do czynienia z podobnym problemem wkrótce.

+0

To jest zasadniczo to, co musisz zrobić, ale istnieją sposoby, aby to zrobić (używając contrib.contenttypes). Zobacz moją odpowiedź. –

+0

Witaj Carl, nie jestem w stanie zobaczyć twojej odpowiedzi. Mógłbyś odesłać, lub podać pomocny link. Dzięki –

+0

Nieważne, mam to. Dziękuję Carl za wyjaśnienie. –

Powiązane problemy