作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
亚历山大喜欢从零开始创建和构建专家应用程序. 他擅长使用Python、PHP和JavaScript解决问题.
9
In this tutorial, 我们将看看Django开发人员经常犯的一些常见错误以及避免这些错误的方法. 即使你是一个熟练的Django开发人员,本教程也很有用, 比如在静态资产中维护难以管理的大型设置或命名冲突, 不仅仅局限于第一次接触Django的新开发者.
Django是一个免费的开源Python web框架,它帮助解决了常见的开发挑战,并允许您灵活地构建, 结构良好的应用程序. Django有很多现成的现代特性. For me personally, the Admin, 对象关系映射工具(ORM), Routing, 和模板特性使Django成为我的第一选择,因为应用程序需要大量的工作, 而我和其他开发者一样喜欢我的工作, 我想在这些基本的重复性任务上花尽可能少的时间. Django允许你在不牺牲灵活性的情况下完成所有这些.
Django的杀手级特性是一个强大的可配置管理界面,它可以自动构建?)从你的模型的模式和管理面板模型,让你感觉像一个向导. 通过Admin界面, 用户可以配置很多东西,包括访问控制列表(ACL)。, 行级权限和操作, filters, orders, widgets, forms, extra URL helpers, 以及任何你能想到的东西. 我相信每个应用程序都需要一个管理面板——如果还没有的话, 这只是一个时间问题,直到您的基本应用程序需要一个. 使用Django admin,你可以快速灵活地创建一个.
Django有一个强大的ORM,可以与所有主流数据库兼容. 由于它是惰性的,所以与其他orm不同,它只在需要时访问数据库. 它支持所有主要的SQL指令(和函数),您可以从Python源代码中使用这些指令(和函数),并且由于Python的特性而感觉非常舒适.
Django的模板引擎既灵活又强大. 你可以使用很多标准 filters and tags 以及为您的项目创建新的自定义过滤器和标签. 除了Django模板,Django还支持其他模板引擎, 它还提供了一个API,可以通过模板处理的标准快捷功能轻松集成其他模板引擎.
Django还有很多其他重要的特性,比如URL路由器,它可以解析传入的请求,并从路由器模式中构建新的URL. 总的来说,Django框架是一种愉快的体验,无论何时你需要帮助,只要阅读 documentation.
不要对项目依赖项使用Python的全局环境, 因为它会产生依赖冲突. Python不能同时使用多个包版本. 如果不同的项目需要同一包的不同不兼容版本,这可能是一个问题.
这个错误通常是由不了解Python的环境隔离特性的新Python和Django开发人员犯的.
有很多方法可以隔离您的环境,但最常见的方法是:
virtualenvwrapper
instead of virtualenv
.要我说,我更喜欢 virtualenv
用于项目依赖隔离和管理的Python包和Docker容器.
requirements.txt
File每个新的Python项目都应该以 requirements.txt 文件和一个新的隔离环境. 通常通过 pip/easy_install
但别忘了把它们加到你的 requirements.txt
file too. This makes it easier (possible (更合适)将项目部署到服务器上, 或者让团队成员在自己的机器上启动项目.
此外,同样重要的是 pin 中的依赖项的特定版本 requirements.txt
file. Usually, 不同版本的包提供不同的模块, functions, and function parameters; even a minor version change in a dependency can break your package. 这是一个非常严重的问题,如果您的项目是实时的,并且您此后定期安排部署, without versioning, 您的构建系统将始终安装软件包的最新可用版本.
始终为生产固定您的包! 就我个人而言,我使用一个非常好的工具,叫做 pip-tools which helps me do this. 它提供了一组命令行工具来帮助管理依赖项. 它会自动生成 requirements.txt
它不仅固定了你的依赖,还固定了你的整个依赖树, 其中包括依赖项的依赖项.
Sometimes, 您只希望更新依赖项列表中的一些包(例如, 只有Django/Flask/任何框架或工具), 如果使用“pip freeze”,则不知道哪个包对应哪个依赖项, 所以你不能升级依赖项. With pip-tools, however, 它会根据您固定的依赖项自动固定包, 因此,它会自动解析哪些包需要更新. As a bonus, 您还可以确切地知道哪个包来自哪个依赖项,因为它是如何用注释标记它们的 requirements.txt
file.
为了谨慎起见,最好也备份依赖项源文件! 在文件系统中保留一份副本, a Git-managed folder, S3 folder, FTP, SFTP—wherever, but have it on hand. 曾经有过这样的例子 一个相对较小的未列出的包破坏了NPM上的大量包. Pip提供了一个工具,可以将所有必需的依赖项作为源文件下载, read more by running pip help download
.
有时在应用程序中使用一个小的Python函数是个好主意 views.py
文件,特别用于测试或实用程序视图, but generally, 您应该在应用程序中使用基于类的视图(cbv).
cbv是提供抽象类的通用视图,这些抽象类实现了由专业人员构建的通用web开发任务,并涵盖了所有通用行为. 他们有一个很棒的结构化API, 当您使用cbv时,您可以使用面向对象编程的所有优点. 它使您的源代码更加清晰易读. 忘记为清单使用Django标准视图函数的痛苦吧, CRUD operations, forms processing, etc. 你只是扩展合适的CBV为您的视图和覆盖类属性或函数(通常一个函数返回一个属性,你可以添加任何逻辑那里面条从你的源代码中使用视图函数而不是CBV的情况下)配置视图行为.
For example, 你可以在你的项目中有不同的混合,覆盖基本的CBV行为来构建视图上下文, 在行级别检查授权, 从应用程序结构自动构建模板路径, 集成智能缓存, and more.
我构建了一个名为 Django Template Names, 哪个基于应用程序名称和视图类名称来标准化视图的模板名称. 我每天都用它,它节省了我发明名字的很多时间. 简单地把混合在你的CBV -类细节(TemplateNames, DetailView):
它将开始发挥作用! Of course, 你可以覆盖我的功能,并添加移动响应模板, 不同的用户代理模板, 或者任何你想要的东西.
在视图而不是模型中编写应用程序逻辑意味着您已经将属于模型的代码编写到视图中, 让模特变“胖”,让模特变“瘦”.”
你应该写胖模型,瘦视图.
将逻辑分解为模型上的小方法. 这允许您从多个来源(管理界面UI)多次使用它, front-end UI, API endpoints, 多个视图)在几行代码中,而不是复制粘贴大量的代码. 下次你给用户发邮件的时候, 使用电子邮件功能扩展模型,而不是在控制器中编写此逻辑.
这也使您的代码更容易进行单元测试,因为您可以在一个地方测试电子邮件逻辑, 而不是在每个控制器中重复发生这种情况.
你可以在 Django Best Practices project. 解决方案很简单:编写胖模型和瘦视图, 所以让我们在你的下一个项目中做这件事(或者重构你当前的项目).
Even the new Django项目设置文件 has a lot of settings. In a real project, 一个设置文件增长到700多行配置,并且将变得难以维护, 尤其是当你的开发者, production, 而登台环境都需要定制配置.
您可以手动划分配置文件并创建自定义加载器, 但我想向您介绍一个很好的、经过良好测试的Python包, Django Split Settings,是我与人合著的.
该包提供两个函数-optional
and include
-它支持通配符的路径和导入配置文件在相同的上下文中, 使用先前加载的文件中声明的配置项构建配置变得简单. 它不会影响Django的性能,你可以在任何项目中使用它.
看看最小配置示例:
from split_settings.工具导入可选,包括
include(
'components/base.py',
'components/database.py',
'components/*.py',
#项目不同环境设置
optional('envs/devel/*.py'),
可选(“env /生产/ *.py'),
可选(“env /临时/ *.py'),
#用于任何本地设置
可选(“local_settings.py'),
)
任何Django项目都由多个应用程序组成. In Django notation, an application 是一个Python包,它至少包含 __init__.py
and models.py
files; in the latest Django versions, models.py
is no longer required. __init__.py
is enough.
Django应用程序可以包含Python模块, Django-specific模块 (views, URLs, models, admin, forms, template tags, etc), static files, templates, database migrations, management commands, unit tests, and more. 您应该将您的整体应用程序分成小的, reusable applications using simple logic. 你应该能够用一两个简短的句子描述应用程序的整个目的. 例如:“允许用户通过电子邮件注册和激活他们的帐户.”
这是一个好主意是调用项目文件夹 project
把申请放到 project/apps/
. 然后,将所有应用程序依赖项放入它们自己的子文件夹中.
Examples:
项目/应用程序/浏览器名称/静态/浏览器名称/
项目/应用程序/浏览器名称/ templatetags /浏览器名称.py
项目/应用程序/浏览器名称/模板/浏览器名称/
始终在子文件夹中添加应用程序名称的前缀,因为所有静态文件夹都合并到一个文件夹中, 如果两个或多个应用程序有 js/core.js
文件,最后一个应用程序 settings.INSTALLED_APPLICATIONS
会推翻之前的吗. 我曾经在当前的项目中遇到过这个bug,并浪费了大约6个小时的调试时间,直到我意识到另一个开发人员已经覆盖了这个bug static/admin/js/core.js
因为该团队正在实现自定义SPA管理面板,并以相同的方式命名他们的文件.
下面是一个门户应用程序的示例结构,该应用程序有很多资源和Python模块.
root@c5b96c395cfb:/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个目录,14个文件
Using such a structure, 您可以随时将应用程序导出到另一个Python包中并再次使用它. 您甚至可以将其作为开放源代码包发布到PyPi中,或者将其移动到另一个文件夹中.
你最终会得到这样一个项目结构:
root@c5b96c395cfb:/test# tree -L
.
├── 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
In a real project, of course, 它会更加复杂, 但这种结构使事情更简单、更清晰.
STATICFILES_DIRS
and STATIC_ROOT
迷惑新手Django开发者静态文件是指在应用使用过程中不会发生变化的资产.g., JavaScript, CSS,图像,字体等. 在Django中,它们只在部署过程中被“收集”到一个公共目录中.
In development mode—python manage.py runserver
-Django使用 STATICFILES_FINDERS
setting. 列表中列出的文件夹中查找所请求的静态文件 STATICFILES_DIRS
setting. 如果失败,Django会尝试使用 django.contrib.staticfiles.finders.AppDirectoriesFinder
, which looks in the static
项目中每个已安装应用程序的文件夹. 这允许您编写可重用的应用程序,这些应用程序附带它们自己的静态文件.
在生产环境中,你可以使用像Nginx这样的独立web服务器来提供静态服务. web服务器不知道Django项目应用程序的结构,也不知道静态文件分布在哪个文件夹中. 幸运的是,Django提供了collect静态管理命令 python manage.py collectstatic
, which walks through STATICFILES_FINDERS
并从应用程序复制所有静态文件 static
中列出的文件夹和文件夹 STATICFILES_DIRS
目录中指定的目录 STATIC_ROOT
setting. 这允许使用与Django开发模式服务器相同的逻辑解析静态文件资源,并将所有静态文件放在web服务器的一个地方.
Don’t forget to run collectstatic
在您的生产环境中!
STATICFILES_STORAGE
Django模板加载器STATICFILES_STORAGE
让我们谈谈生产环境资产管理. 我们可以提供最好的用户体验,如果我们使用“资产永不过期”的政策(你可以阅读更多关于 here). 这意味着我们所有的静态文件都应该被web浏览器缓存数周、数月甚至数年. 换句话说,您的用户应该只下载您的资产一次!
That’s cool, 我们可以在Nginx配置中为静态文件文件夹设置几行代码, 但是缓存无效呢? 如果用户只下载我们的资产一次, 如果你更新了你的标志会发生什么, fonts, JavaScript, 或者菜单中项目的文本颜色? 为了绕过这个问题,您应该为每个部署上的静态文件生成唯一的url和文件名!
我们可以简单地用 ManifestStaticFilesStorage as STATICFILES_STORAGE
(注意,散列只在 DEBUG=false
mode) and running the collectstatic
上面讨论的管理命令. 这将减少对您的生产网站的资产请求计数,并使您的网站渲染得更快.
另一个很酷的Django特性是缓存模板加载器, 在每个模板渲染上都不会重新加载和解析模板文件. 模板解析是一项非常昂贵的操作,需要使用大量资源. By default, Django模板在每次请求时都会被解析, but this is bad, 特别是在生产过程中, 在哪里可以在短时间内处理数千个请求.
Check out the cached.Loader
配置部分提供了一个很好的示例,并详细说明了如何做到这一点. Don’t use the loader in development mode because it doesn’t reload parsed templates from the file system; you will need to restart your project using python manage.py startapp
每次修改模板时. 这在开发过程中可能很烦人,但对于生产环境来说是完美的.
Django提供了一个非常好的特性,叫做 Management Commands. 只需使用它,而不是重新发明轮子并为您的项目实用程序编写原始Python脚本.
Also, check out the Django Extensions 包,它是Django的自定义扩展的集合. 也许有人已经实现了您的命令! 已经有很多常见的任务命令.
Django和Python有数千种现成的解决方案. Try Googling before you write something that is not unique; there’s probably a feature-rich solution that already exists.
试着把事情简单化. Google first! Install, configure, extend, 如果你找到一个高质量的包,就集成到你的项目中, and of course, 当你有机会的时候为开源做贡献.
首先,这里是我自己的Django公共包列表:
不要重复自己(DRY)!
I really like DRY methodology; that’s why I created Django skeleton 作为一个便利的工具,它有一些非常简洁的功能:
dist
文件夹将被Django收集 collectstatic
command.它是一个随时可用的Django骨架,为你的下一个项目从零开始, hopefully, 通过引导项目为您节省大量时间. Webpack有最小的基本配置,但它也安装了预配置的SASS来处理 .scss
files.
亚历山大喜欢从零开始创建和构建专家应用程序. 他擅长使用Python、PHP和JavaScript解决问题.
9
世界级的文章,每周发一次.
世界级的文章,每周发一次.
Join the Toptal® community.