models.py staje się ogromny, jaki jest najlepszy sposób na rozbicie tego?


91

Wskazówki od mojego przełożonego: „Chcę uniknąć umieszczania jakiejkolwiek logiki w models.py. Odtąd używajmy jej tylko jako klas dostępu do bazy danych i zachowajmy całą logikę w klasach zewnętrznych, które używają klas modeli, lub zawiń je”.

Czuję, że to niewłaściwa droga. Uważam, że trzymanie logiki z dala od modeli tylko po to, aby plik był mały, to zły pomysł. Jeśli logika jest najlepsza w modelu, to właśnie tam powinna iść, niezależnie od rozmiaru pliku.

Czy jest więc prosty sposób na użycie po prostu obejmuje? Mówiąc językiem PHP, chciałbym zaproponować przełożonemu, że właśnie models.pyuwzględniliśmy () modele klas z innych miejsc. Koncepcyjnie pozwoliłoby to modelom na posiadanie całej logiki, jakiej oczekujemy, jednocześnie zmniejszając rozmiar pliku poprzez zwiększenie liczby plików (co prowadzi do mniej problemów z kontrolą wersji, takich jak konflikty itp.).

Czy jest więc prosty sposób na usunięcie klas modeli z pliku models.py, ale czy modele nadal działają ze wszystkimi narzędziami Django? A może istnieje zupełnie inne, ale eleganckie rozwiązanie ogólnego problemu z „dużym” plikiem models.py? Każdy wkład będzie mile widziany.


7
Znasz instrukcję importu, prawda?
balpha

7
PS. Nie mam na myśli tego ofensywnie, po prostu chcę wiedzieć, gdzie jesteś.
balpha

1
Tak, ale nie wiedziałem, czy narzędzia administracyjne django będą działały po prostu używając instrukcji importu do ściągania modeli. Wolałbym zapytać, niż spędzać dużo czasu na wypróbowywaniu importu zwykłego ole, aby dowiedzieć się, że narzędzia django nie współpracują z nimi dobrze. Przyznaję, że jestem nowszy w Pythonie i django, więc prawdopodobnie rozumiem tylko prostą instrukcję importu ...
Eddified

Odpowiedzi:


64

Django zostało zaprojektowane tak, aby umożliwić tworzenie wielu małych aplikacji zamiast jednej dużej aplikacji.

Wewnątrz każdej dużej aplikacji znajduje się wiele małych aplikacji, które walczą o wolność.

Jeśli models.pyczujesz się duży, robisz za dużo. Zatrzymać. Zrelaksować się. Rozkładać się.

Znajdź mniejsze, potencjalnie wielokrotnego użytku komponenty lub części aplikacji. Nie masz do faktycznie używać ich. Po prostu pomyśl o nich jako o potencjalnie wielokrotnego użytku.

Zastanów się nad ścieżkami aktualizacji i zdekomponuj aplikacje, które możesz chcieć zastąpić któregoś dnia. Nie trzeba faktycznie je zastąpić, ale można uznać je jako „moduł” stand-alone programowania, które mogą się zastąpić czymś chłodnicy w przyszłości.

Mamy kilkanaście aplikacji, z których każda model.pyma nie więcej niż około 400 linii kodu. Wszystkie są dość skoncentrowane na mniej niż pół tuzinie dyskretnych definicji klas. (To nie są twarde ograniczenia, to obserwacje dotyczące naszego kodu).

Rozkładamy się wcześnie i często.


1
dokładnie w punkcie. każda nietrywialna aplikacja internetowa byłaby kilkoma małymi „aplikacjami”. weź wskazówkę o wkładzie i innych popularnych aplikacjach, uwierzytelnianie użytkownika to jedna aplikacja, tagowanie to druga, profile użytkowników jeszcze jeden itd.
Javier

4
Chociaż jest to „właściwy” sposób i warto wiedzieć, nie jest to dokładnie to, czego szukałem. Przepraszam, jeśli nie było sposobu, aby dowiedzieć się, jakiej odpowiedzi szukałem. :)
Eddified

@Eddified: jeśli tego nie zrobisz, będzie tylko gorzej. Zacznij dzielić się teraz.
S.Lott,

Co zabawne, w tej chwili słucham Jacoba Kaplana Mossa (z OSCON-u), który dokładnie to wyjaśnia ze świetnymi i mocno uzasadnionymi szczegółami ;-).
Alex Martelli

13
W tym przypadku odpowiedź Glenna Maynarda jest znacznie lepsza. Dzielenie złożonej aplikacji internetowej na wiele aplikacji jest z pewnością dobrą praktyką, ale tak samo jest z refaktoryzacją pliku model.py W RAMACH aplikacji. Te dwie akcje mogą być ortogonalne.
Erik

108

Naturalne jest, że klasy modelu zawierają metody do działania na modelu. Jeśli mam model Book z metodą book.get_noun_count(), to właśnie tam należy - nie chcę pisać " get_noun_count(book)", chyba że metoda faktycznie należy do innego pakietu. (Może - na przykład, jeśli mam pakiet dostępu do interfejsu API Amazona za pomocą „ get_amazon_product_id(book)”).

Wzdrygnąłem się, gdy dokumentacja Django sugerowała umieszczenie modeli w jednym pliku i poświęciłem kilka minut od samego początku, aby wymyślić, jak podzielić go na odpowiedni podpakiet.

site/models/__init__.py
site/models/book.py

__init__.py wygląda jak:

from .book import Book

więc nadal mogę napisać „from site.models import Book”.


Poniższe informacje są wymagane tylko w przypadku wersji starszych niż Django 1.7, patrz https://code.djangoproject.com/ticket/3591

Jedyna sztuczka polega na tym, że musisz jawnie ustawić aplikację każdego modelu z powodu błędu w Django: zakłada się, że nazwa aplikacji jest trzecią do ostatniej pozycji w ścieżce modelu. „site.models.Book” daje w wyniku „site”, co jest poprawne; „site.models.book.Book” powoduje, że nazwa aplikacji to „modele”. To dość paskudny hack ze strony Django; powinien prawdopodobnie przeszukać listę zainstalowanych aplikacji pod kątem dopasowania przedrostka.

class Book(models.Model):
    class Meta: app_label = "site"

Prawdopodobnie możesz użyć klasy bazowej lub metaklasy, aby to uogólnić, ale jeszcze się tym nie przejmowałem.


2
+1 Użyłem tego z powodzeniem. Chociaż S. Lott ma rację, że wiele aplikacji jest dobrym pomysłem, jest to rozwiązanie tu i teraz.
Alexander Ljungberg

35
Nie widzę większych korzyści z dzielenia rzeczy na kilka aplikacji, gdy modele są blisko i wewnętrznie powiązane.
Glenn Maynard,

2
To mnie interesuje. Przeczytałem opublikowany link do wiki django i stwierdziłem, że: „Zostało to zweryfikowane pod kątem działania bez klasy meta app_labels w bieżącej gałęzi głównej”. Czy to oznacza, że ​​jeśli pracujesz z główną gałęzią, możemy odrzucić elementy Meta: app_label? Jest to mylące, ponieważ jest po komentarzu na temat biletu, aby rozwiązać ten problem.
Dan.StackOverflow

2
Właśnie testowałem z tunerem (dzisiaj, r11286); jeśli nazwa_aplikacji nie jest ustawiona, model po prostu nie pojawia się w „sqlall nazwa_aplikacji” i prawdopodobnie nie zostanie utworzony przez syncdb (ale nie używam tego, więc nie mogę go przetestować). To dość zagmatwany przypadek błędu, ponieważ nie powoduje żadnych błędów; po prostu po cichu się nie pojawia.
Glenn Maynard

2
Wow, prawie 10 lat później i nadal uwielbiam to rozwiązanie. Zgodziłem się, że jest to znacznie lepsze podejście niż dzielenie kodu na mniejsze aplikacje, co moim zdaniem może prowadzić do bazy kodu, o której trudno jest zrozumieć.
Michael Hays

5

Nie do końca rozumiem, który z wielu możliwych problemów możesz mieć. Oto kilka możliwości z odpowiedziami:

  • wiele modeli w tym samym pliku

    Umieść je w osobnych plikach. Jeśli istnieją zależności, użyj importu, aby pobrać dodatkowe modele.

  • dodatkowe funkcje logiczne / narzędziowe w models.py

    Umieść dodatkową logikę w osobnych plikach.

  • statyczne metody wybierania niektórych instancji modelu z bazy danych

    Utwórz nowego menedżera w oddzielnym pliku.

  • metody oczywiście związane z modelem

    save, __unicode__ i get_absolute_url to przykłady.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.