2009-07-21 3 views
80

Indicazioni dal mio supervisore: "Voglio evitare di inserire alcuna logica nel models.py. Da qui in avanti, usiamolo come solo classi per accedere al database e mantenere tutta la logica in classi esterne che utilizzano le classi dei modelli, oppure avvolgeteli. "models.py sta diventando enorme, qual è il modo migliore per romperlo?

Mi sento come se fosse la strada sbagliata. Sento che mantenere la logica fuori dai modelli solo per mantenere il file piccolo è una cattiva idea. Se la logica è la migliore nel modello, è esattamente dove dovrebbe andare, indipendentemente dalle dimensioni del file.

Quindi c'è un modo semplice per utilizzare include? In PHP-speak, mi piacerebbe proporre al supervisore che abbiamo solo models.py include() le classi del modello da altri posti. Concettualmente, ciò consentirebbe ai modelli di avere tutta la logica che vogliamo, mantenendo però le dimensioni del file verso il basso aumentando il numero di file (il che porta a meno problemi di controllo di revisione come i conflitti, ecc.).

Quindi, c'è un modo semplice per rimuovere le classi del modello dal file models.py, ma i modelli funzionano ancora con tutti gli strumenti di Django? Oppure esiste una soluzione completamente diversa ma elegante al problema generale di un file model.py "grande"? Qualsiasi input sarebbe apprezzato.

+6

Sai la dichiarazione di importazione, giusto? – balpha

+6

PS. Non intendo questo in modo offensivo, voglio solo sapere dove sei. – balpha

+0

Sì, ma non sapevo se gli strumenti di amministrazione di django avrebbero funzionato usando solo le istruzioni import per inserire i Modelli. Preferirei chiedere qui piuttosto che passare un sacco di tempo a provare a usare le semplici importazioni di petrolio solo per scoprire che gli strumenti di django non giocano bene con loro. Ammetto di essere più recente a Python e Django, quindi probabilmente sono solo a una semplice comprensione della dichiarazione di importazione ... – Eddified

risposta

61

Django è progettato per consentire di creare molte piccole applicazioni invece di un'unica grande applicazione.

All'interno di ogni applicazione di grandi dimensioni ci sono molte piccole applicazioni che lottano per essere libere.

Se il tuo models.py sembra grande, stai facendo troppo. Stop. Rilassare. Decomporsi.

Trova componenti o componenti di piccole dimensioni, potenzialmente riutilizzabili. Non è necessario il in realtà riutilizzarli. Pensa a loro come potenzialmente riutilizzabili.

Considerare i percorsi di aggiornamento e decomporre le applicazioni che si potrebbero voler sostituire un giorno. Non è necessario sostituire , ma è possibile considerarli come un "modulo" autonomo di programmazione che potrebbe essere sostituito con qualcosa di più interessante in futuro.

Abbiamo una dozzina di applicazioni, ciascuna model.py non è più di circa 400 righe di codice. Sono tutti abbastanza concentrati su meno di circa mezza dozzina di definizioni di classi discrete. (Questi non sono limiti difficili, sono osservazioni sul nostro codice.)

Ci decomponiamo presto e spesso.

+1

proprio sul punto. qualsiasi webapp non banale sarebbe più piccole "app". fai un cenno di contrib e altre app popolari, l'autenticazione utente è un'app, il tagging è un altro, i profili utente uno di più, ecc. – Javier

+4

Mentre questo è il modo "giusto", e utile sapere, non è proprio quello Stavo cercando. Mi scuso se non c'era modo di sapere che tipo di risposta stavo cercando.:) – Eddified

+0

@Eddified: se non lo fai, peggiorerà solo. Inizia a dividere ora. –

93

È naturale che le classi modello contengano metodi per operare sul modello. Se ho un modello Book, con un metodo book.get_noun_count(), è qui che appartiene - Non voglio scrivere "get_noun_count(book)", a meno che il metodo non appartenga effettivamente intrinsecamente ad altri pacchetti. (Potrebbe, per esempio, se ho un pacchetto per accedere all'API di Amazon con "get_amazon_product_id(book)".)

I cringei quando la documentazione di Django suggeriva di mettere i modelli in un unico file, e ho preso qualche minuto dall'inizio per capire come dividerlo in un sotto pacchetto adeguato.

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

__init__.py assomiglia:

from .book import Book 

così posso ancora scrivere "dal site.models importare Libro".


Di seguito sono richiesti solo per le versioni precedenti a Django 1.7, vedere https://code.djangoproject.com/ticket/3591

L'unico trucco è che è necessario impostare in modo esplicito l'applicazione di ogni modello, a causa di un bug in Django : presuppone che il nome dell'applicazione sia la penultima entrata nel percorso del modello. "site.models.Book" risulta in "sito", che è corretto; "site.models.book.Book" fa pensare che il nome dell'applicazione sia "models". Questo è un bel brutto attacco da parte di Django; dovrebbe probabilmente cercare l'elenco delle applicazioni installate per una corrispondenza prefissata.

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

probabilmente si potrebbe utilizzare una classe di base o metaclasse generalizzare questo, ma non ho disturbato con ancora.

+2

+1. Ho usato questo con successo. Mentre S. Lott ha ragione in più app è una buona idea, questa è la soluzione qui e ora. –

+0

Questo è il modo per farlo. Ulteriori informazioni sono disponibili sul sito Web di Django: http://code.djopoproject.com/wiki/CookBookSplitModelsToFiles –

+0

@Alexander Ljungberg: non sono convinto facilmente che sia più semplice della suddivisione di app. Le app possono essere separate semplicemente dal 'models.py' originale. Spesso è solo un po 'più di taglia e incolla da urls.py, views.py, tests.py e models.py. –

4

Non riesco a capire quale dei molti possibili problemi si possano avere. Qui ci sono alcune possibilità con le risposte:

  • più modelli nello stesso file

    metterli in file separati. Se esistono delle dipendenze, utilizzare import per inserire i modelli aggiuntivi .

  • estranee funzioni logiche/utilità in models.py

    Mettere la logica in più in file separati.

  • metodi statici per la selezione di alcuni casi modello dal database

    Creare un nuovo Manager in un file separato.

  • metodi ovviamente legati al modello

    salvare, __unicode__ e get_absolute_url sono esempi.