Django开发人员犯的10大错误

在这篇文章中,我们将介绍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框架是一种令人愉悦的体验,每当需要帮助时,只需阅读文档即可,接下来我们说一下在使用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项目均应以requirements.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)来配置视图行为,则需要自己写代码。

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

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

错误四:代码逻辑写在了视图中而不是模型中
在视图中而不是模型中编写应用程序逻辑意味着已经将模型中的代码编写到视图中,从而使其“很胖”,而模型“很瘦”。

正确的事应该编写胖模型,瘦的视图。

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

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

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

错误5:庞大且难以管理的设置文件
甚至新的Django项目设置文件也有很多设置。 在真实的项目中,设置文件会增长到700多行配置,并且将变得难以维护,尤其是当开发,生产和环境都需要自定义配置时。

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

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

查看最小配置示例:

错误之六:全部在一个app中,不良的应用程序结构和不正确的资源放置
任何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模块的门户网站应用程序的示例结构

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

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

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

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

静态文件是不会随着应用程序的使用而更改的内容,例如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搜索。可能已经存在功能丰富的解决方案。

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

首先,这是我自己的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文件。

原文:https://www.toptal.com/django/django-top-10-mistakes