【问题标题】:Split views.py in several files在几个文件中拆分views.py
【发布时间】:2023-06-10 10:07:01
【问题描述】:

我的views.py 太大了,很难找到合适的视图。

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

我可以对models.py 做同样的事情吗?

【问题讨论】:

  • 我将我的大型(7k 行)views.py 文件拆分为单独的文件,速度的提升非常显着。

标签: python django


【解决方案1】:

基本上,您可以随意放置代码。只要确保您相应地更改导入语句,例如对于urls.py中的意见。

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

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

【讨论】:

    【解决方案2】:

    在 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会在

    中寻找view1
    1. views.py,这是第一个(原始)案例中发生的情况

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

    使用这种解决方案,您可能无需更改 urls.py 中的 importurlpatterns 参数

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

    from viewsa import *
    from viewsb import *
    

    我实际上不知道速度问题(但我怀疑是否存在)。

    对于模型来说,这可能有点困难。

    【讨论】:

    • 能否在您的示例中添加与 view1 或 view2 匹配的 url 模式?因为我有这个问题....
    • 我试过这样做,但是当我去导入我的模型时(从 app.models 导入 MyModel 或从模型导入 MyModel)Python 抱怨模型不存在。
    • 删除根目录下的views.py可以吗?
    • 这个解决方案对我不起作用(与@ChrisMiller 的错误相同。我的解决方案:在__init__.pyfrom myapp.views.viewsa import *。请注意,您不能再拥有views.py(或至少它不会被读取 @ShiftNTab: Error for not found your views in views.py)。希望对您有所帮助!
    • 我必须使用句点:from .viewsa import * -- 如果这是一个普遍的问题/解决方案,可能值得更正答案。
    【解决方案3】:

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

    【讨论】:

    • 这实际上是不正确的——它可以用模型来完成。见:code.djangoproject.com/ticket/4470
    • 啊,很高兴知道,谢谢 :-) 我一直认为模型以及它们如何在应用程序包中存在更多的魔力。在我的回复中删除了关于模型的行。
    • 很高兴我能帮上忙,后来我意识到这个链接实际上解释了如何更好地使用模型:blog.amber.org/2009/01/19/…
    【解决方案4】:

    简单的回答:是的。

    最好是创建一个名为 views 的目录,然后在你的 urls.py 中做:

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

    【讨论】:

      【解决方案5】:

      我以前必须这样做(为了清楚起见)

      我这样做的方法是创建一个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 ;)

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

          我一直在尝试将其放入我的 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 新手,所以我还在研究它对速度/安全性/易用性的影响。

          【讨论】:

            【解决方案8】:

            假设如果您有一个名为:password_generator.py 的文件,那么在 views.py 中添加:from password_generator import *

            然后您可以从views.py 调用该模块的函数。

            【讨论】:

              【解决方案9】:

              只是为了分享,我对 Vincent Demeester 的回答有些疑问。一切都很好,除了 init.py 文件,我必须这样写:

              __init__.py

              from .viewsa import *
              from .viewsb import *
              

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

              【讨论】:

                【解决方案10】:

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

                from ..models import ModelName
                

                成功了!!

                【讨论】: