Разделить views.py в нескольких файлах

153

Мой views.pyстал слишком большим, и трудно найти правильный взгляд.

Как мне разбить его на несколько файлов и затем импортировать? Это связано с потерей скорости?

Могу ли я сделать то же самое с models.py?

барин
источник
4
Я разделил свой большой (7k строк) файл views.py на отдельные файлы, и увеличение скорости было значительным.
user1261774

Ответы:

190

В Django все является модулем Python (* .py). Вы можете создать папку представлений с __init__.pyвнутренней частью, и вы все равно сможете импортировать ваши представления, потому что это также реализует модуль Python. Но пример был бы лучше.

Ваш оригинал views.pyможет выглядеть так:

def view1(arg):
    pass

def view2(arg):
   pass

Со следующей структурой папок / файлов она будет работать так же:

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

Быстрое объяснение будет: когда вы пишете на from views import view1Python будет искать view1 в

  1. views.py, что происходит в первом (оригинальном) случае

  2. views/__init__.py, что происходит во втором случае. Здесь __init__.pyможет предоставить метод view1, потому что он импортирует его.

С такого рода решения, не может иметь никакой необходимости изменять importили urlpatternS аргументы вurls.py

Если у вас есть много методов в каждом новом файле просмотр, вы можете найти его полезным , чтобы сделать импорт в views/__init__.pyиспользовании *, как это:

from viewsa import *
from viewsb import *

Я действительно не знаю о проблемах со скоростью (но я сомневаюсь, что они есть).

Для моделей это может быть немного сложно.

Винсент Деместер
источник
2
Не могли бы вы добавить шаблон URL, который соответствует view1 или view2 в вашем примере? Потому что у меня проблемы с этим ....
Паскаль Кляйн
2
Я пытался сделать это, но когда я иду на импорт моих моделей (из app.models import MyModel или из моделей import MyModel) Python жалуется, что модель не существует.
Крис Миллер
Это нормально, если мы удалим views.py в корневом каталоге?
Роэл
6
Это решение не работает для меня (та же ошибка, что и для @ChrisMiller. Мое решение: in __init__.py:. from myapp.views.viewsa import *Обратите внимание, что у вас больше не может быть views.py (или, по крайней мере, он не будет прочитан @ShiftNTab: ошибка не найти ваши взгляды в views.py). Надеюсь, это поможет!
ThePhi
А как насчет соглашения об именах: имя файла должно быть единственным или множественным? Например: views.car.pyпротивviews.cars.py
гиваль
21

Я должен был сделать это раньше (для ясности)

Я сделал так, чтобы создать viewsкаталог, а затем создать файл с именем__init__.py

Теперь, когда вы звоните в свой urls.py, вам просто нужно добавить еще одну часть

Например, ранее вы могли позвонить:

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

Теперь вы можете позвонить что-то вроде

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

Это, конечно, при условии, что у вас есть views/year.pyфункции indexи user;)

Mez
источник
10

По сути, вы можете поместить свой код, где пожелаете. Просто убедитесь, что вы изменили операторы импорта соответственно, например, для представлений в urls.py.

Не зная вашего фактического кода, трудно предложить что-то значимое. Может быть , вы можете использовать какие - префикс имени файла, например views_helper.py, views_fancy.py, views_that_are_not_so_often_used.pyили так ...

Другой вариант - создать viewsкаталог с каталогом __init__.py, куда вы импортируете все подпредставления . Если вам нужно большое количество файлов, вы можете создавать больше вложенных подпредставлений по мере роста ваших просмотров ...

Мик
источник
8

Просто для того, чтобы поделиться, у меня возникли некоторые проблемы с ответом Винсента Деместера. Все хорошо, кроме файла init .py, я должен написать так:

__init__.py :

from .viewsa import *
from .viewsb import *

Таким образом, мне все еще не нужно менять свой importметод в urls.py. Я на Python 3.6.1 и Django 1.11.4 .

увлекаются
источник
5

Простой ответ: да.

Лучше всего создать каталог с именем views, а затем в вашем urls.py сделать:

import views
...
url(r'^classroom$', views.school.klass, name="classroom"),
Питер Бенгтссон
источник
1

Я разделил почти все представления в моих приложениях в папку представлений ( конечно, с init .py). Однако я не импортирую все подпредставления в файле init .py, как предлагали некоторые ответы. Вроде работает просто отлично.

DrBloodmoney
источник
1

Так как Django ожидает, что представление будет вызываемым объектом, вы можете поместить его в любое место в вашей PYTHONPATH. Так что вы можете, например, просто сделать новый пакет myapp.views и разместить там представления в нескольких модулях. Вам, естественно, придется обновить свой urls.py и другие модули, которые ссылаются на эти вызываемые виды.

Хорст Гутманн
источник
1
Это на самом деле неверно - это можно сделать с помощью моделей. См .: code.djangoproject.com/ticket/4470
Джонатан Бергер,
1
Ах, приятно знать, спасибо :-) Я всегда думал, что с моделями и их содержанием в пакете приложений связано немного больше магии. Удалена строка о моделях в моем ответе.
Хорст Гутман
Рад, что смог помочь, позже я понял, что эта ссылка на самом деле объясняет, как это делается с моделями намного лучше: blog.amber.org/2009/01/19/…
Джонатан Бергер,
1

Я играл с положить это в моем 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))

Я все еще новичок в Python, поэтому я все еще смотрю, как он влияет на скорость / безопасность / простоту использования.

Etos
источник
1

Предположим, если у вас есть файл с именем: password_generator.pyзатем внутри views.pyadd:from password_generator import *

Затем вы можете вызвать функцию этого модуля из views.py.

Абхай
источник
1

Ответ Винсента Деместера превосходен! но для меня зависимый ответ работал как шарм. Я столкнулся с трудностями при переносе базы данных. Ошибка указывает на строку, в которую импортируется первая модель, и говорит, что не удалось распознать модуль моего приложения. Много искал, но не смог найти решение, но позже я импортировал модель так:

from ..models import ModelName

Это сработало!!

Башар
источник