个性化阅读
专注于IT技术分析

Django开发人员犯的10大错误

本文概述

在本教程中, 我们将介绍Django开发人员经常犯的一些常见错误以及避免这些错误的方法。即使你是熟练的Django开发人员, 本教程也很有用, 因为错误(例如保持难以管理的大设置或命名静态资产中的冲突)不仅限于新开发人员, 他们对Django进行了首次尝试。

Django是一个免费和开放源代码的Python Web框架, 可以帮助解决常见的开发难题, 并允许你构建灵活, 结构合理的应用程序。 Django开箱即用, 具有许多现代功能。就我个人而言, 管理, 对象关系映射工具(ORM), 路由和模板功能使Django成为我的首选, 因为应用程序需要大量的工作, 并且尽管我尽我所能地享受开发人员的工作, 但我还是想花点时间在这些基本的重复任务上花费尽可能少的时间。 Django允许你执行所有这些操作而不会影响灵活性。

Django的杀手级功能是一个功能强大的可配置管理界面, 可从模型的架构和管理面板模型自动(自动?)构建, 使你感觉像个向导。通过Admin界面, 用户可以配置许多内容, 包括访问控制列表(ACL), 行级权限和操作, 过滤器, 订单, 小部件, 表单, 额外的URL帮助器以及你可以想象的任何其他内容。我相信每个应用程序都需要一个管理面板-如果尚未, 基本应用程序需要一个时间只是一个时间问题。使用Django admin, 你可以快速灵活地创建一个。

Django有一个功能强大的ORM, 可直接使用所有主要数据库。由于它是惰性的, 因此它仅在需要时才访问数据库, 这不同于其他ORM。它支持你可以从Python源代码使用的所有主要SQL指令(和函数), 并且由于Python的功能而感到非常舒适。

Django的模板引擎同时非常灵活和强大。你可以使用许多标准过滤器和标签, 也可以为项目创建新的自定义过滤器和标签。 Django支持其他模板引擎以及Django模板, 并且它提供了一个API, 可通过标准的快捷方式功能轻松集成其他模板引擎, 以进行模板处理。

Django还有许多其他重要功能, 例如URL路由器, 它可以解析传入的请求并根据路由器模式构建新的URL。总体而言, Django框架是一种令人愉悦的体验, 只要需要帮助, 只需阅读文档。

错误1:使用全局系统Python环境获取项目依赖项

不要将Python的全局环境用于项目依赖项, 因为它会产生依赖项冲突。 Python不能同时使用多个软件包版本。如果不同的项目需要同一程序包的不同不兼容版本, 则可能会出现问题。

这个错误通常是由不了解Python环境隔离功能的新Python和Django开发人员犯的。

有很多方法可以隔离你的环境, 但是最常见的方法是:

  • virtualenv:一个Python软件包, 它生成一个Python环境文件夹, 并具有用于[停用]环境和管理该环境中已安装的Python软件包的脚本。这是我最喜欢的方法, 因为它是完成工作的最简单方法。通常, 我在项目文件夹附近创建环境。
  • virtualenvwrapper:一个Python软件包, 在全球范围内安装, 并提供用于创建/删除/激活/等的工具集。虚拟环境。所有虚拟环境都存储在一个文件夹中(可以通过环境变量WORKON_HOME覆盖该文件夹)。我看不到使用virtualenvwrapper而不是virtualenv的任何优势。
  • 虚拟机(VM):没有比专门用于你的应用程序的整个虚拟机更好的隔离了。有很多工具可供选择, 包括VirtualBox(免费), VMware, Parallels和Proxmox(我个人很喜欢, 并且有免费版本)。结合使用Vagrant之类的VM自动化工具, 这将是一个非常强大的解决方案。
  • 容器:在过去的几年中, 我几乎在每个项目中都使用Docker, 尤其是在我从头开始的每个新项目中。 Docker是一个了不起的工具, 它提供了许多功能, 并提供了许多用于容器自动化的第三方工具。它具有层缓存功能, 可以非常快速地重建容器。在容器中, 我使用全局系统Python环境, 因为每个容器都有其自己的文件系统, 并且项目在较高级别上是隔离的。 Docker允许新的团队成员更快地开始项目工作, 特别是如果他们有Docker经验。

如果你问我, 我更喜欢virtualenv Python软件包和Docker容器, 用于项目依赖项的隔离和管理。

错误2:未在requirements.txt文件中固定项目依赖项

每个新的Python项目均应以require.txt文件和新的隔离环境开头。通常, 你通过pip / easy_install安装所有软件包, 但不要忘记也将它们添加到你的requirements.txt文件中。这样可以更轻松(可能更合适)在服务器上部署项目, 或使团队成员在自己的计算机上引导项目。

此外, 将特定版本的依赖项固定在requirements.txt文件中也同样重要。通常, 不同版本的程序包提供不同的模块, 功能和功能参数。甚至依赖项中的较小版本更改都可能破坏你的程序包。如果你的项目正在运行并且你有定期计划的部署, 这是一个非常严重的问题, 因为在没有版本控制的情况下, 你的构建系统将始终安装软件包的最新可用版本。

始终固定你的包装以进行生产!就个人而言, 我使用了一个非常好的工具pip-tools, 它可以帮助我实现这一目标。它提供了一组命令行工具, 可帮助管理依赖项。它会自动生成requirements.txt文件, 该文件不仅固定你的依赖关系, 还固定整个依赖关系树, 其中包括依赖关系的依赖关系。

有时, 你只想更新依赖项列表中的某些软件包(例如, 仅Django / Flask /任何框架或实用程序), 如果你使用” pip Frozen”, 则不知道哪些依赖关系适用于哪些软件包, 因此你无法升级依赖项。但是, 使用pip-tools时, 它会根据你固定的依赖关系自动固定软件包, 因此它会自动解决需要更新的软件包。另外, 你还可以确切知道哪个程序包来自哪个依赖项, 因为它是如何在requirements.txt文件中用注释标记它们的。

要格外小心, 这也是一个备份依赖项源文件的好主意!随时随地在文件系统, Git管理的文件夹, S3文件夹, FTP, SFTP等文件中保留一个副本, 但请随时准备。曾经有一个案例, 一个相对较小的软件包被取消列出, 在npm上破坏了许多软件包。 Pip有用地提供了用于将所有必需的依赖项下载为源文件的工具, 请通过运行pip help download了解更多信息。

错误之三:使用老式的Python函数代替基于类的视图

有时, 最好在应用程序的views.py文件中使用一个小的Python函数, 尤其是对于测试或实用程序视图, 但是通常, 应在应用程序中使用基于类的视图(CBV)。

CBV是通用视图, 提供抽象类, 以实现由专业人员构建的通用Web开发任务, 并涵盖所有常见行为。它们具有惊人的结构化API, 使用CBV时, 你可以使用面向对象编程的所有优点。它使你的源代码更加清晰易读。不用再使用Django标准视图函数进行列表, CRUD操作, 表单处理等工作了。你只需为视图扩展合适的CBV并覆盖类属性或函数(通常, 函数会返回属性, 并且你可以在其中添加任何逻辑)如果使用视图功能(而不是CBV)来配置视图行为, 则从你的源代码中制作意大利面条。

例如, 你可以在项目中使用不同的混入, 这些混入会覆盖用于构建视图上下文的基本CBV行为, 在行级别检查授权, 从应用程序结构自动构建模板路径, 集成智能缓存等等。

我构建了名为Django Template Names的程序包, 该程序包根据应用程序名称和视图类名称标准化视图的模板名称。我每天都在使用它, 它为发明名称节省了很多时间。只需将mixin放入CBV中(类Detail(TemplateNames, DetailView):), 即可开始工作!当然, 你可以覆盖我的功能, 并添加移动响应模板, 用于用户代理的不同模板或任何其他想要的东西。

错误四:写胖视图和瘦模型

在视图中而不是模型中编写应用程序逻辑意味着你已将属于模型的代码编写到视图中, 从而使其”很胖”, 而模型”很瘦”。

你应该编写胖模型, 瘦的视图。

将逻辑分解为模型上的小方法。这使你可以在几行代码中从多个源(管理界面UI, 前端UI, API端点, 多个视图)多次使用它, 而无需复制粘贴大量代码。因此, 下次你向用户发送电子邮件时, 请使用电子邮件功能扩展模型, 而不是在控制器中编写此逻辑。

这也使你的代码更易于进行单元测试, 因为你可以在一个地方测试电子邮件逻辑, 而不是在每个进行此测试的控制器中重复测试。

你可以在Django最佳实践项目中阅读有关该问题的更多信息。解决方案很简单:编写胖模型和狭窄视图, 所以让我们在下一个项目中进行操作(或重构当前项目)。

错误5:庞大且难以管理的设置文件

甚至新的Django项目设置文件也有很多设置。在实际的项目中, 设置文件会增长到700多个配置行, 并且将变得难以维护, 尤其是当你的开发, 生产和登台环境都需要自定义配置时。

你可以手动分割配置文件并创建自定义加载程序, 但是我想向你介绍一个我共同编写的, 经过良好测试的Python软件包Django Split Settings。

该软件包提供了两个功能(可选和包含), 它们支持路径的通配符并在同一上下文中导入配置文件, 从而使使用先前加载的文件中声明的配置条目来构建配置变得简单。它不会影响Django的性能, 你可以在任何项目中使用它。

查看最小配置示例:

from split_settings.tools import optional, include

include(
    'components/base.py', 'components/database.py', 'components/*.py', # the project different envs settings
    optional('envs/devel/*.py'), optional('envs/production/*.py'), optional('envs/staging/*.py'), # for any local settings
    optional(‘local_settings.py'), )

错误6:多合一应用程序, 不良的应用程序结构和不正确的资源放置

任何Django项目都包含多个应用程序。用Django表示法, 应用程序是一个Python包, 其中至少包含__init__.py和models.py文件。在最新的Django版本中, 不再需要models.py。 __init__.py就足够了。

Django应用程序可以包含Python模块, 特定于Django的模块(视图, URL, 模型, 管理, 表单, 模板标签等), 静态文件, 模板, 数据库迁移, 管理命令, 单元测试等。你应该使用简单的逻辑将整体应用程序划分为小型, 可重用的应用程序。你应该可以用一两个简短的句子来描述应用程序的全部用途。例如:”允许用户通过电子邮件注册和激活其帐户。”

最好将项目文件夹命名为project并将应用程序放置在project / apps /中。然后, 将所有应用程序依赖项放入它们自己的子文件夹中。

例子:

  • 静态文件:project / apps / appname / static / appname /
  • 模板标签:project / apps / appname / templatetags / appname.py
  • 模板文件:project / apps / appname / templates / appname /

始终在子文件夹中为应用程序名称加上前缀, 因为所有静态文件夹都合并到一个文件夹中;如果两个或多个应用程序具有js / core.js文件, 则settings.INSTALLED_APPLICATIONS中的最后一个应用程序将覆盖前一个应用程序。我曾经在当前项目中遇到此错误, 并且损失了大约六个小时的调试时间, 直到我意识到另一个开发人员已覆盖static / admin / js / core.js, 因为该团队正在实现自定义SPA管理面板并以相同的方式命名其文件。

这是具有大量资源和Python模块的门户网站应用程序的示例结构。

[email protected]:/test# tree project/apps/portal/
project/apps/portal/
├── __init__.py
├── admin.py
├── apps.py
├── management
│   ├── __init__.py
│   └── commands
│       ├── __init__.py
│       └── update_portal_feeds.py
├── migrations
│   └── __init__.py
├── models.py
├── static
│   └── portal
│       ├── css
│       ├── img
│       └── js
├── templates
│   └── portal
│       └── index.html
├── templatetags
│   ├── __init__.py
│   └── portal.py
├── tests.py
├── urls.py
└── views.py

11 directories, 14 files

使用这种结构, 你可以随时将应用程序导出到另一个Python包中, 然后再次使用它。你甚至可以将其作为开源软件包发布在PyPi中, 或将其移动到另一个文件夹中。

你将最终得到一个像这样的项目结构:

[email protected]:/test# tree -L 3
.
├── deploy
│   ├── chef
│   └── docker
│       ├── devel
│       └── production
├── docs
├── logs
├── manage.py
├── media
├── project
│   ├── __init__.py
│   ├── apps
│   │   ├── auth
│   │   ├── blog
│   │   ├── faq
│   │   ├── pages
│   │   ├── portal
│   │   └── users
│   ├── conf
│   ├── settings.py
│   ├── static
│   ├── templates
│   ├── urls.py
│   └── wsgi.py
└── static
    └── admin
        ├── css
        ├── fonts
        ├── img
        └── js

25 directories, 5 files

当然, 在实际的项目中, 它将更加复杂, 但是这种结构使事情变得更简单, 更清洁。

错误7:STATICFILES_DIRS和STATIC_ROOT混淆了新手Django开发人员

STATICFILES_DIRS? STATIC_ROOT?

静态文件是不会因应用程序的使用而改变的资产, 例如JavaScript, CSS, 图像, 字体等。在Django中, 它们仅在部署过程中”收集”到公共目录中。

在开发模式下(python manage.py runserver), Django使用STATICFILES_FINDERS设置搜索静态文件。默认情况下, 它尝试在STATICFILES_DIRS设置中列出的文件夹中查找请求的静态文件。万一失败, Django会尝试使用django.contrib.staticfiles.finders.AppDirectoriesFinder查找文件, 该文件将查找项目中每个已安装应用程序的静态文件夹。这使你可以编写可重用的应用程序, 这些应用程序带有它们自己的静态文件。

在生产中, 你可以使用独立的Web服务器(例如Nginx)来提供静态服务。 Web服务器对Django项目应用程序的结构或静态文件的分发文件夹一无所知。幸运的是, Django为你提供了收集静态管理命令python manage.py collectstatic, 该命令遍历STATICFILES_FINDERS并从静态应用程序复制所有静态文件STATICFILES_DIRS中列出的文件夹和文件夹到你在STATIC_ROOT设置中指定的目录中。这允许使用与Django开发模式服务器相同的逻辑来解析静态文件资源, 并将所有静态文件放在Web服务器的一个位置。

不要忘记在生产环境中运行collectstatic!

错误8:默认STATICFILES_STORAGE, 生产中的Django模板加载器

STATICFILES_STORAGE

让我们谈谈生产环境资产管理。如果我们使用”资产永不过期”策略(你可以在此处了解更多信息), 则可以提供最佳的用户体验。这意味着我们所有的静态文件都应该由网络浏览器缓存数周, 数月甚至数年。换句话说, 你的用户只能下载一次你的资产!

太酷了, 我们可以在Nginx配置中为静态文件文件夹添加几行代码, 但是缓存失效呢?如果用户仅下载一次我们的资产, 那么如果你更新菜单中某个项目的徽标, 字体, JavaScript或文本颜色会怎样?为了避免这种情况, 你应该在每次部署时为我们的静态文件生成唯一的URL和文件名!

我们可以通过将ManifestStaticFilesStorage用作STATICFILES_STORAGE来简单地做到这一点(注意, 仅在DEBUG = false模式下启用散列)并运行上面讨论的collectstatic管理命令。这将减少对你的生产网站的资产请求计数, 并使你的网站渲染更快。

缓存的Django模板加载器

Django的另一个很酷的功能是缓存的模板加载器, 它不会在每个模板渲染器上重新加载和解析模板文件。模板解析是一项非常昂贵的操作, 并占用大量资源。默认情况下, 对每个请求都解析Django模板, 但这很不好, 尤其是在生产期间, 你可以在短时间内处理成千上万个请求。

请查看cached.Loader配置部分, 以获取一个很好的示例以及有关如何执行此操作的详细信息。不要在开发模式下使用加载程序, 因为它不会从文件系统中重新加载已解析的模板;你需要在每次模板更改时使用python manage.py startapp重新启动项目。在开发过程中这可能很烦人, 但对于生产环境而言却是完美的。

错误9:实用程序或脚本的纯Python脚本

Django提供了一个非常好的功能, 称为”管理命令”。只需使用它即可, 而不是为项目实用程序重新发明轮子和编写原始Python脚本。

另外, 请查看Django Extensions软件包, 它是Django自定义扩展的集合。也许有人已经实现了你的命令!已经有很多常见的任务命令。

错误十:重塑方向盘

不要重新发明轮子

Django和Python有数千种现成的解决方案。在编写非唯一的东西之前, 请尝试使用Google搜索。可能已经存在功能丰富的解决方案。

只是尝试使事情变得简单。 Google第一!如果找到优质的软件包, 请安装, 配置, 扩展和集成到你的项目中, 当然, 如果有机会, 请为开源做贡献。

首先, 这是我自己的Django公共软件包列表:

  • Django宏URL使使用宏在Django应用程序中轻松编写(和读取)URL模式成为可能。
  • Django模板名称是一个很小的混合项, 可让你轻松地标准化CBV模板名称。
  • django-split-settings可让你将Django设置组织到多个文件和目录中。轻松覆盖和修改设置。在设置文件路径中使用通配符, 并将设置文件标记为可选。

不要重复自己(DRY)!

我真的很喜欢DRY方法论;这就是为什么我创建Django框架作为便捷工具的原因, 该工具开箱即用地具有一些非常简洁的功能:

  • 由docker-compose管理的用于开发/生产的Docker映像, 可让你轻松编排容器列表。
  • 用于生产部署的简单Fabric脚本。
  • Django Split Settings软件包的配置, 包括基本和本地源的设置。
  • Webpack已集成到项目中-Django将通过collectstatic命令仅收集dist文件夹。
  • 配置了所有基本Django设置和功能, 例如生产中的可缓存Django模板, 哈希散列的静态文件, 集成的调试工具栏, 日志记录等。

从头开始为你的下一个项目提供现成的Django Skeleton, 并有望通过引导项目节省大量时间。 Webpack的基本配置最少, 但是还预先安装了SASS, 以处理.scss文件。

赞(0)
未经允许不得转载:srcmini » Django开发人员犯的10大错误

评论 抢沙发

评论前必须登录!