2009-07-21 10 views
80

Wegbeschreibung von meinem Vorgesetzten: "Ich möchte keine Logik in die models.py setzen. Ab hier, verwenden wir das als nur Klassen für den Zugriff auf die Datenbank, und behalten Sie alle Logik in externen Klassen, die die Modelle Klassen verwenden, oder wickle sie ein. "models.py wird riesig, was ist der beste Weg, um es zu brechen?

Ich fühle mich wie das ist der falsche Weg zu gehen. Ich denke, dass es eine schlechte Idee ist, die Logik aus den Modellen herauszuhalten, nur um die Datei klein zu halten. Wenn die Logik im Modell am besten ist, sollte sie unabhängig von der Dateigröße wirklich verwendet werden.

So gibt es eine einfache Möglichkeit, einfach zu verwenden umfasst? In PHP-Sprache möchte ich dem Supervisor vorschlagen, dass wir models.py include() die Modellklassen von anderen Orten haben. Konzeptionell würde dies den Modellen ermöglichen, alle Logik zu haben, die wir wollen, aber die Dateigröße gering halten, indem wir die Anzahl der Dateien erhöhen (was zu weniger Revisionskontrollproblemen wie Konflikten usw. führt).

Gibt es also eine einfache Möglichkeit, Modellklassen aus der models.py-Datei zu entfernen, aber die Modelle funktionieren trotzdem mit allen Django-Tools? Oder gibt es eine ganz andere, aber elegante Lösung für das allgemeine Problem einer "großen" models.py-Datei? Jede Eingabe würde geschätzt werden.

+6

Sie kennen die Importanweisung, richtig? – balpha

+6

PS. Ich meine das nicht offensiv, ich will nur wissen wo du bist. – balpha

+0

Ja, aber ich wusste nicht, ob die Admin-Tools von django nur mit import-Anweisungen arbeiten würden, um die Models einzubinden. Ich würde lieber hier fragen, als viel Zeit damit zu verbringen, einfache Importe zu testen, nur um herauszufinden, dass die Werkzeuge von Django nicht gut mit ihnen spielen. Ich gebe zu, ich bin neuer zu Python und Django, also bin ich wahrscheinlich nur bei einem einfachen Verständnis der Import-Anweisung ... – Eddified

Antwort

61

Django wurde entwickelt, damit Sie viele kleine Anwendungen statt einer großen Anwendung erstellen können.

Innerhalb jeder großen Anwendung sind viele kleine Anwendungen, die kämpfen, frei zu sein.

Wenn Ihre models.py fühlt sich groß an, Sie tun zu viel. Halt. Entspannen Sie Sich. Zersetzen.

Suchen Sie kleinere, potenziell wiederverwendbare kleine Anwendungskomponenten oder Teile. Sie müssen tatsächlich nicht wiederverwenden. Denken Sie nur an sie als potenziell wiederverwendbar.

Betrachten Sie Ihre Upgrade-Pfade und zerlegen Sie Anwendungen, die Sie vielleicht eines Tages ersetzen möchten. Sie müssen nicht eigentlich ersetzen, aber Sie können sie als ein eigenständiges "Modul" der Programmierung betrachten, die in Zukunft mit etwas Kühler ersetzt werden könnte.

Wir haben etwa ein Dutzend Anwendungen, jede model.py ist nicht mehr als etwa 400 Zeilen Code. Sie sind alle auf weniger als etwa ein halbes Dutzend diskrete Klassendefinitionen fokussiert. (Dies sind keine harten Grenzen, sie sind Beobachtungen über unseren Code.)

Wir zerlegen früh und oft.

+1

direkt am Punkt. Jede nicht-triviale Webapp würde mehrere kleine "Apps" sein. Nehmen Sie einen Hinweis auf die Contrib und andere beliebte Apps, Benutzerauthentifizierung ist eine App, Tagging ist eine andere, Benutzerprofile eine weitere, etc. – Javier

+4

Während dies der "richtige" Weg ist, und hilfreich zu wissen, ist es nicht ganz was Ich suchte. Ich entschuldige mich, wenn ich nicht wissen konnte, welche Art von Antwort ich suchte.:) – Eddified

+0

@Edified: Wenn du das nicht machst, wird es nur noch schlimmer. Fange jetzt an zu teilen. –

93

Es ist natürlich, dass Modellklassen Methoden zum Arbeiten mit dem Modell enthalten. Wenn ich ein Buchmodell habe, mit einer Methode book.get_noun_count(), dann gehört es dazu - ich möchte nicht "get_noun_count(book)" schreiben müssen, es sei denn, die Methode gehört eigentlich zu einem anderen Paket. (Zum Beispiel, wenn ich ein Paket für den Zugriff auf Amazon API mit "get_amazon_product_id(book)" habe.)

Ich erschrak, als Djangos Dokumentation vorgeschlagen, Modelle in einer einzigen Datei zu setzen, und ich habe ein paar Minuten von Anfang an um herauszufinden, wie man es in ein richtiges Unterpaket aufteilt.

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

__init__.py wie folgt aussieht:

from .book import Book 

so kann ich noch schreiben "aus site.models Buch importieren".


Die folgenden nur für die Versionen 1.7 vor Django erforderlich ist, finden https://code.djangoproject.com/ticket/3591

Der einzige Trick ist, dass Sie explizit jedes Modell der Anwendung einstellen müssen, aufgrund eines Fehlers in Django : Es wird davon ausgegangen, dass der Anwendungsname der drittletzte Eintrag im Modellpfad ist. "site.models.Book" führt zu "site", was korrekt ist; "site.models.book.Book" denkt, dass der Name der Anwendung "models" lautet. Dies ist ein ziemlich hässlicher Hack auf Djangos Seite; Es sollte wahrscheinlich die Liste installierter Anwendungen nach einer Präfix-Übereinstimmung durchsuchen.

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

Sie könnten wahrscheinlich eine Basisklasse oder metaclass verwenden, um dies zu verallgemeinern, aber ich habe nicht mit, dass noch gestört.

+2

+1 aufgerufen, die ich mit Erfolg verwendet habe. Während S. Lott in mehreren Apps recht hat, ist dies eine gute Idee. –

+0

Dies ist der Weg, es zu tun. Weitere Informationen finden Sie auf der Django-Website: http://code.djangoproject.com/wiki/CookBookSplitModelsToFiles –

+0

@Alexander Ljungberg: Ich bin nicht so leicht davon überzeugt, dass dies einfacher ist als das Aufteilen von Apps. Apps können ganz einfach vom ursprünglichen 'models.py' getrennt werden. Oft ist es nur ein wenig mehr als cut and paste von urls.py, views.py, tests.py und models.py. –

4

Ich kann nicht ganz bekommen, welche von vielen möglichen Problemen Sie haben könnten. Hier sind einige Möglichkeiten, mit Antworten:

  • mehrere Modelle in der gleichen Datei

    sie in separate Dateien Put. Wenn Abhängigkeiten vorhanden sind, verwenden Sie den Import, um die zusätzlichen Modelle einzubinden.

  • Fremd Logik/Nutzenfunktionen in models.py

    Setzen Sie die zusätzliche Logik in separate Dateien.

  • statische Methoden für einige Modellinstanzen aus der Datenbank Auswahl

    Erstellen Sie ein neues Manager in einer separaten Datei.

  • Methoden offensichtlich auf das Modell im Zusammenhang

    speichern, __unicode__ und get_absolute_url sind Beispiele.

Verwandte Themen