Dividi views.py in diversi file


153

Mio views.py è diventato troppo grande ed è difficile trovare la giusta visione.

Come posso dividerlo in più file e quindi importarlo? Implica una perdita di velocità?

Posso fare lo stesso con models.py?


4
Ho diviso il mio grande file views.py (7k righe) in file separati e l'aumento della velocità è stato significativo.
user1261774

Risposte:


190

In Django tutto è un modulo Python (* .py). Puoi creare una cartella di visualizzazione con un __init__.pyinterno e sarai comunque in grado di importare le tue visualizzazioni, poiché questo implementa anche un modulo Python. Ma un esempio sarebbe migliore.

Il tuo originale views.pypotrebbe apparire così:

def view1(arg):
    pass

def view2(arg):
   pass

Con la seguente struttura di cartelle / file funzionerà allo stesso modo:

views/
   __init__.py
   viewsa.py
   viewsb.py

viewsa.py :

def view1(arg):
    pass

viewsb.py :

def view2(arg):
    pass

__init__.py :

from viewsa import view1
from viewsb import view2

La rapida spiegazione sarebbe: quando scrivi from views import view1Python cercherà view1 in

  1. views.py, che è ciò che accade nel primo caso (originale)

  2. views/__init__.py, che è ciò che accade nel secondo caso. Qui, __init__.pyè in grado di fornire il metodo view1 perché lo importa.

Con questo tipo di soluzione, potresti non aver bisogno di cambiare importourlpattern s argomentiurls.py

Se hai molti metodi in ogni nuovo file di visualizzazione, potresti trovare utile effettuare le importazioni in views/__init__.pyuso *, in questo modo:

from viewsa import *
from viewsb import *

In realtà non conosco i problemi di velocità (ma dubito che ce ne siano).

Per i modelli potrebbe essere un po 'difficile.


2
Potresti aggiungere un pattern URL che corrisponda a view1 o view2 nel tuo esempio? Perché sto avendo problemi con questo ...
Pascal Klein il

2
Ho provato a farlo, ma quando vado a importare i miei modelli (da app.models importa MyModel o dai modelli import MyModel) Python si lamenta che il modello non esiste.
Chris Miller,

Va bene se eliminiamo views.py nella directory principale?
Roel

6
Questa soluzione non funziona per me (stesso errore di @ChrisMiller. La mia soluzione: in __init__.py:. from myapp.views.viewsa import *Nota che non puoi più avere un views.py (o almeno non verrà letto @ShiftNTab: Errore per non trovare i tuoi punti di vista in views.py). Spero che sia d'aiuto!
ThePhi

Che dire della convenzione di denominazione: il nome del file dovrebbe essere singolare o plurale? Es .: views.car.pyvsviews.cars.py
guival

21

Ho dovuto farlo prima (per amor di chiarezza)

Il modo in cui l'ho fatto è stato creare una viewsdirectory, quindi creare un file chiamato__init__.py

Ora, quando chiami il tuo urls.py, devi semplicemente aggiungere un'altra parte

Ad esempio, in precedenza, potresti aver chiamato: -

url(r'^calendar/(?P<year>\d\d\d\d)/$', 'myproject.calendar.views.year')
url(r'^calendar/(?P<year>\d\d\d\d)/(?P<user>[a-z]+)/$', 'myproject.calendar.views.year_by_user')

Ora puoi chiamare qualcosa sulla falsariga di

url(r'^calendar/(?P<year>\d\d\d\d)/$', 'myproject.calendar.views.year.index')
url(r'^calendar/(?P<year>\d\d\d\d)/(?P<user>[a-z]+)/$', 'myproject.calendar.views.year.user')

Questo ovviamente presuppone che tu abbia views/year.pycontenuto le funzioni indexe user;)


10

Fondamentalmente, puoi inserire il tuo codice, ovunque tu voglia. Assicurati solo di modificare le dichiarazioni di importazione di conseguenza, ad es. Per le viste inurls.py .

Non conoscendo il tuo codice attuale è difficile suggerire qualcosa di significativo. Forse è possibile utilizzare una sorta di prefisso del nome file, ad esempio views_helper.py, views_fancy.py, views_that_are_not_so_often_used.pyo giù di lì ...

Un'altra opzione sarebbe quella di creare una viewsdirectory con un __init__.py, in cui importare tutte le visualizzazioni secondarie . Se hai bisogno di un numero elevato di file, puoi creare più visualizzazioni secondarie nidificate man mano che le visualizzazioni aumentano ...


8

Solo per la condivisione, ho avuto un po 'di problemi con la risposta di Vincent Demeester. Va tutto bene tranne che nel file init .py, devo scrivere in questo modo:

__init__.py :

from .viewsa import *
from .viewsb import *

In questo modo non ho ancora bisogno di cambiare il mio importmetodo in urls.py. Sono su Python 3.6.1 e Django 1.11.4 .


5

Risposta semplice: Sì.

La cosa migliore è creare una directory chiamata views e quindi nel tuo urls.py fare:

import views
...
url(r'^classroom$', views.school.klass, name="classroom"),

1

Ho diviso quasi tutte le visualizzazioni nelle mie app in una cartella di visualizzazioni (con un init .py ovviamente). Tuttavia, non importare tutte le visualizzazioni secondarie in init .py come suggerito da alcune delle risposte. Sembra funzionare bene.


1

Dal momento che Django si aspetta solo che la vista sia un oggetto richiamabile, puoi metterlo dove preferisci nel tuo PYTHONPATH. Quindi, ad esempio, puoi creare un nuovo pacchetto myapp.views e inserire le viste in più moduli lì. Dovrai naturalmente aggiornare urls.py e altri moduli che fanno riferimento a questi callable di visualizzazione.


1
Questo in realtà non è corretto - può essere fatto con i modelli. Vedi: code.djangoproject.com/ticket/4470
Jonathan Berger,

1
Ah, buono a sapersi, grazie :-) Ho sempre pensato che ci fosse un po 'più di magia con le modelle e il modo in cui vivono nel pacchetto dell'app. Rimossa la linea sui modelli nella mia risposta.
Horst Gutmann,

Sono contento di poterti
Jonathan Berger

1

Ho giocato a mettere questo nel mio init .py:

import os

currPath = os.path.realpath(os.path.dirname(__file__))

dirFiles = []
for root, dirs, files in os.walk(currPath):
    for name in files:
        if name.endswith('.py') and not name.startswith('_'): 
            dirFiles.append(name.strip('.py'))

for f in dirFiles:
    exec("from %s import %s" % (f,f))

Sono ancora nuovo su Python, quindi sto ancora cercando l'effetto che ha sulla velocità / sicurezza / facilità d'uso.


1

Supponiamo che tu abbia un file chiamato: password_generator.pyquindi all'interno views.pyaggiungi:from password_generator import *

Quindi puoi chiamare la funzione di quel modulo da views.py.


1

La risposta di Vincent Demeester è superba! ma per me la risposta del dipendente ha funzionato come un incantesimo. Ho riscontrato difficoltà nella migrazione del database. L'errore indica la riga in cui viene importato il primo modello e dice che non è stato possibile riconoscere il mio modulo app. Ho cercato molto ma non sono riuscito a trovare una soluzione, ma in seguito ho importato il modello in questo modo:

from ..models import ModelName

Ha funzionato!!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.