将views.py拆分为多个文件


153

我的views.py体积太大了,很难找到正确的视图。

如何将其拆分为多个文件,然后导入?是否涉及速度损失?

我可以这样models.py吗?


4
我将较大的(7k行)views.py文件拆分为单独的文件,并且速度显着提高。
user1261774

Answers:


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 view1的Python会寻找在厂景

  1. views.py,这就是第一种(原始)情况

  2. views/__init__.py,这是第二种情况。在这里,__init__.py能够提供view1方法,因为它可以导入它。

使用这种解决方案,您可能无需更改import或更改urlpattern参数urls.py

如果每个新视图文件中都有很多方法,那么views/__init__.py使用导入可能会很有用*,如下所示:

from viewsa import *
from viewsb import *

我实际上不了解速度问题(但我怀疑是否有任何问题)。

对于模型而言,可能有点困难。


2
您能否在示例中添加与view1或view2匹配的网址格式?因为我对此有
Pascal Klein

2
我尝试这样做,但是当我导入模型(从app.models导入MyModel或从模型导入MyModel)时,Python抱怨该模型不存在。
克里斯·米勒

如果我们删除根目录中的views.py,可以吗?
Roel

6
该解决方案对我不起作用(与@ChrisMiller相同的错误。我的解决方案:in __init__.py:中from myapp.views.viewsa import *。请注意,您再也不能具有views.py了(或者至少不会被读取@ShiftNTab:错误)希望对您
有所

命名约定如何:文件名应为单数还是复数?例如:views.car.pyvsviews.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包含indexuser;)


10

基本上,您可以将代码放在任意位置。只需确保您相应地更改了导入语句,例如针对中的视图即可urls.py

不知道您的实际代码很难提出有意义的建议。也许你可以使用某种类型的文件名前缀,例如views_helper.pyviews_fancy.pyviews_that_are_not_so_often_used.py或使...

另一个选择是创建一个views目录__init__.py,其中要导入所有子视图。如果您需要大量文件,则可以随着视图的增长而创建更多的嵌套子视图。


8

只是为了分享,文森特·德梅斯特(Vincent Demeester)的回答有点问题。除了init .py文件外,一切都很好,我必须这样写:

__init__.py

from .viewsa import *
from .viewsb import *

这样,我仍然不需要import在urls.py中更改我的方法。我正在使用Python 3.6.1Django 1.11.4


5

简单的答案:是的。

最好是创建一个名为views的目录,然后在您的urls.py中执行以下操作:

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

1

我将应用程序中的几乎所有视图都拆分为一个views文件夹(当然还有一个init .py)。但是,我不像某些答案所建议的那样将所有子视图导入init .py中。似乎工作正常。


1

由于Django只希望视图是可调用的对象,因此您可以将其放置在PYTHONPATH中的任何位置。因此,您可以例如仅创建一个新程序包myapp.views并将视图放入那里的多个模块中。自然,您将不得不更新urls.py和其他引用这些视图可调用对象的模块。


1
这实际上是不正确的-可以通过模型来完成。请参阅:code.djangoproject.com/ticket/4470
Jonathan Berger

1
啊,很高兴知道,谢谢您:-)我一直认为模型和模型在应用程序包中的作用涉及更多魔力。在我的回复中删除了有关模型的行。
Horst Gutmann

很高兴能为您提供帮助,后来我意识到,该链接实际上说明了如何更好地使用模型:blog.amber.org/2009/01/19/…–
Jonathan Berger

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新手,所以我仍在研究它对速度/安全性/易用性有什么影响。


1

假设您有一个名为:的文件,password_generator.py然后在其中views.py添加:from password_generator import *

然后,您可以从调用该模块的功能views.py


1

文森特·德梅斯特Vincent Demeester)的回答太棒了!但是对我来说,瘾君子的回答就像一个魅力。我在迁移数据库时遇到困难。该错误指示导入了第一个模型的行,并指出无法识别我的应用程序模块。搜索了很多,但是找不到解决方案,但是后来我导入了这样的模型:

from ..models import ModelName

有效!!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.