Podziel plik views.py na kilka plików

153

Mój views.pystał się zbyt duży i trudno znaleźć właściwy widok.

Jak podzielić go na kilka plików, a następnie zaimportować? Czy wiąże się to z utratą prędkości?

Czy mogę zrobić to samo z models.py?

Barin
źródło
4
Podzieliłem mój duży (7 tys. Wierszy) plik views.py na oddzielne pliki i wzrost szybkości był znaczący.
user1261774

Odpowiedzi:

190

W Django wszystko jest modułem Pythona (* .py). Możesz utworzyć folder widoku z __init__.pywnętrzem i nadal będziesz mógł importować swoje widoki, ponieważ implementuje to również moduł Pythona. Ale przykład byłby lepszy.

Twój oryginał views.pymoże wyglądać tak:

def view1(arg):
    pass

def view2(arg):
   pass

Z następującą strukturą folderów / plików będzie działać tak samo:

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

Szybkie wyjaśnienie byłoby: gdy piszesz from views import view1Python będzie szukać w view1

  1. views.py, co dzieje się w pierwszym (oryginalnym) przypadku

  2. views/__init__.py, co dzieje się w drugim przypadku. Tutaj __init__.pyjest w stanie zapewnić metodę view1, ponieważ importuje ją.

Dzięki tego rodzaju rozwiązaniu możesz nie mieć potrzeby zmiany importlub urlpatternargumentów wurls.py

Jeśli masz wiele metod w każdym nowym pliku widoku, może się okazać, że warto dokonać importu w views/__init__.pyużytku *, na przykład:

from viewsa import *
from viewsb import *

Właściwie nie wiem o problemach z szybkością (ale wątpię, czy są).

W przypadku modeli może to być trochę trudne.

Vincent Demeester
źródło
2
Czy możesz dodać wzorzec adresu URL, który pasuje do widoku1 lub widoku2 w Twoim przykładzie? Ponieważ mam z tym problemy ...
Pascal Klein
2
Próbowałem to zrobić, ale kiedy idę importować moje modele (z app.models import MyModel lub from models import MyModel), Python narzeka, że ​​model nie istnieje.
Chris Miller,
Czy jest w porządku, jeśli usuniemy views.py w katalogu głównym?
Roel,
6
To rozwiązanie nie działa dla mnie (ten sam błąd niż @ChrisMiller moje rozwiązanie. W __init__.py: from myapp.views.viewsa import *. Pamiętaj, że nie może mieć views.py już (lub przynajmniej nie będą odczytywane @ShiftNTab: Błąd na nie znajdowanie swoich poglądów w views.py). Mam nadzieję, że to pomoże!
ThePhi
A co z konwencją nazewnictwa: czy nazwa pliku powinna być w liczbie pojedynczej czy mnogiej? Np .: views.car.pyvsviews.cars.py
guival
21

Musiałem to zrobić wcześniej (dla jasności)

Sposób, w jaki to zrobiłem, polegał na utworzeniu viewskatalogu, a następnie utworzeniu pliku o nazwie__init__.py

Teraz, kiedy dzwonisz urls.py, po prostu musisz dodać kolejną część

Na przykład wcześniej mogłeś dzwonić: -

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')

Możesz teraz wywołać coś w stylu

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')

To oczywiście przy założeniu, że posiadałeś views/year.pyfunkcje indexi user;)

Mez
źródło
10

Zasadniczo możesz umieścić swój kod, gdziekolwiek chcesz. Tylko upewnij się, że odpowiednio zmieniasz instrukcje importu, np. Dla widoków w urls.py.

Nie znając swojego rzeczywistego kodu, trudno jest zasugerować coś znaczącego. Może użyć jakiś przedrostek nazwy pliku, na przykład views_helper.py, views_fancy.py, views_that_are_not_so_often_used.pyalbo tak ...

Inną opcją byłoby utworzenie viewskatalogu z __init__.py, do którego importujesz wszystkie widoki podrzędne . Jeśli potrzebujesz dużej liczby plików, możesz utworzyć więcej zagnieżdżonych widoków podrzędnych w miarę wzrostu widoków ...

miku
źródło
8

Tylko po to, żeby się podzielić, miałem trochę problemów z odpowiedzią Vincenta Demeestera. Wszystko jest w porządku poza plikiem init .py, muszę napisać w ten sposób:

__init__.py :

from .viewsa import *
from .viewsb import *

W ten sposób nadal nie muszę zmieniać importmetody w urls.py. Jestem na Pythonie 3.6.1 i Django 1.11.4 .

uzależniony
źródło
5

Prosta odpowiedź: tak.

Najlepiej jest utworzyć katalog o nazwie views, a następnie w swoim urls.py zrobić:

import views
...
url(r'^classroom$', views.school.klass, name="classroom"),
Peter Bengtsson
źródło
1

Prawie wszystkie widoki w moich aplikacjach dzielę na folder widoków ( oczywiście z init .py). Nie importuję jednak wszystkich podglądów podrzędnych w pliku init .py, jak sugerowały niektóre odpowiedzi. Wydaje się, że działa dobrze.

DrBloodmoney
źródło
1

Ponieważ Django po prostu oczekuje, że widok będzie obiektem wywoływalnym, możesz umieścić go w dowolnym miejscu w swojej PYTHONPATH. Możesz więc na przykład po prostu utworzyć nowy pakiet myapp.views i umieścić tam widoki w wielu modułach. Będziesz oczywiście musiał zaktualizować swój adres urls.py i inne moduły, które odwołują się do wywołań tych widoków.

Horst Gutmann
źródło
1
W rzeczywistości jest to niepoprawne - można to zrobić za pomocą modeli. Zobacz: code.djangoproject.com/ticket/4470
Jonathan Berger
1
Ach, dobrze wiedzieć, dziękuję :-) Zawsze myślałem, że z modelkami i ich sposobem życia w pakiecie aplikacji jest trochę więcej magii. Usunąłem wiersz o modelach z mojej odpowiedzi.
Horst Gutmann
Cieszę się, że mogłem pomóc, później zdałem sobie sprawę, że ten link faktycznie wyjaśnia, jak to się robi z modelami znacznie lepiej: blog.amber.org/2009/01/19/...
Jonathan Berger
1

Bawiłem się umieszczaniem tego w moim 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))

Wciąż jestem nowy w Pythonie, więc wciąż zastanawiam się, jaki ma to wpływ na szybkość / bezpieczeństwo / łatwość użycia.

EToS
źródło
1

Załóżmy, że masz plik o nazwie: password_generator.pyto w środku views.pydodaj:from password_generator import *

Następnie możesz wywołać funkcję tego modułu z views.py.

Abhay
źródło
1

Odpowiedź Vincenta Demeestera jest znakomita! ale dla mnie odpowiedź uzależnionego działała jak urok. Miałem trudności z migracją bazy danych. Błąd wskazuje wiersz, do którego jest importowany pierwszy model, i mówi, że nie można rozpoznać modułu mojej aplikacji. Dużo szukałem, ale nie mogłem znaleźć rozwiązania, ale później zaimportowałem model w ten sposób:

from ..models import ModelName

Zadziałało!!

Bashar
źródło