Django Web 应用项目:学习笔记
前言
学习框架
此文说明
- 此项目参考于《Python编程:从入门到实践》_第1版_Eric Matthes 中的 “Web应用程序:学习笔记”项目。
- 此项目文件名为 learning_log, 文中涉及的路径都以 learning_log/ 开头。
为什么学
- 完成《Python编程:从入门到实践》中的 “Web应用程序:学习笔记”项目
- 学习 Python Web应用开发,了解 Django 开发框架
- 熟悉 Linux 开发环境
- 掌握 HTML 网页设计知识
- 学习 Web 项目部署
背景知识
关系数据库基础知识。
HTML 基础知识
参考文档
Django 官网: https://docs.djangoproject.com/en/4.0/
django中文网: https://www.django.cn/course/
uwsgi: https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/WSGIquickstart.html
书中有更新的内容: https://ehmatthes.github.io/pcc/updates.html
实现过程
Django 内置模块
以下模块名均省略 django. 前缀,均是项目中涉及到的模块
Module(模块) | Inclusion(包含) | Explanation(解释) |
---|---|---|
http | HttpRequest、HttpResponse、Http404... | http 请求与响应模块 |
db.< name > | models(数据模型)... | Django 数据库系统 |
db.models | Model | 一个模型对应一张数据库关系表 |
db.models.fields | Charfield、TextField... | 模型字段,对应于数据库关系表的列属性 |
db.backends | mysql、sqlite3、postgresql... | Django 支持的数据库后端(引擎) |
db.migrations | Migration | Django 将你对模型所做的更改(添加一个字段,删除一个模型)映射到数据库模式中的一种方式 |
contrib.< name > | admin(网站管理)、auth(用户认证及授权)、messages(消息管理)... | abbr. 贡献(contribution)。包含解决常见 web 开发问题的可选工具,每个工具都是一个应用程序,使用时包含在 settings.py 中的 INSTALLED_APPS 里。 |
contrib.auth | Django 认证系统,处理用户认证和授权。 | |
contrib.auth.models | User、Group、Permission... | 用户认证和授权相关的模型(类)及函数 |
contrib.auth.decorators | login_required()... | 装饰器 |
contrib.staticfiles | 静态文件管理 |
models 与 database 的关系
MVC Web 框架中的 M 即是 models,而 models 直接定义和操纵数据库,所以任何涉及数据存储与交互的 Web 应用都会用到 models。
在 Python 中的 Django Web 框架中,models 里面会定义一些类,一般每一个类对应于数据库中的一张关系表。Django 默认使用 <小写类名>_id
作为这张表的主键。因此在代码中可以直接使用这个“未定义”的关键字。举例如下:
在 models.py 中定义一个 Topic 类:
class Topic(models.Model):
"""A topic the user is learning about"""
text = models.CharField(max_length=200)
在 urls.py 中使用基于 Topic 类创建的关系表的 主键关键字 topic_id:
urlpatterns = [
# Detail page for a single topic
path('topics/<int:topic_id>/', views.topic, name='topic'),
]
项目部署
基本概念
1. 什么是项目部署
应用程序的完成至少有两个阶段,开发和部署。
所谓部署,就是让开发出的产品能够在某一环境中运行起来。
将开发过程中产生的源代码生成可运行的软件包,然后将软件包放到要部署的环境中,通过一些配置使得这个软件包在目标环境上也能够正常工作,这就是完整的部署过程。
这个环境是什么?可以是公司的实体服务器(机房里的服务器),可以是云服务器,也可以是本地服务器(个人电脑),所以相应地部署就分为远程部署和本地部署。
2. 为什么要部署项目
对于一个项目来说,不同人群需要的“产品”类型不一样。假设我们要为某一个公司开发一个网站,开发人员关心的是源代码,而项目管理人员要的是一个可运行的软件包,客户要的是打开网页就能显示预期内容的页面。
我们之所以部署项目,就是想达到客户的访问要求,即看到网站的内容。
开发工作是在本地进行的,这时我们会使用一些编辑器,如 VScode 等,但是这时项目只能在我们本地环境才能正常运行,别人的电脑是访问不到的,要想别人也能够正常使用我们的项目就得进行项目部署。
3. 如何部署项目
部署要做的工作大致分为三步:
- 将源代码打包成 .jar 包或 .war 包
- 将可运行的软件包放到部署平台上
- 配置部署环境,使软件包运行起来
一般来说,我们提到的部署都是远程部署,真正地投入用户使用。
服务器、域名、ICP备案
按如下步骤准备:
-
服务器
购买腾讯云服务器:轻量应用服务器 Linux CentOS 8.0 2核2G4M 300GB/月 (65元/年) -
域名
lightmark.club 光印网 (12/年)
轻松而自由,每笔皆印记。For relax and freedom, every letter is a mark! -
ICP备案
域名购买成功并实名认证后等待3天,在腾讯云官网备案即可。
注意!!!ICP 备案成功后再进行域名解析。 -
域名解析
腾讯云官网 DNS 解析。
Git 版本控制系统
1. 安装配置 Git
如何学习 Git
- 初步了解 Git :
参考《Python编程:从入门到实践》附录D :使用 Git 进行版本控制。在正式进行项目部署前,通过一个小案例进行 Git 学习。 - 官网文档:
https://git-scm.com/site
https://git-scm.com/doc
安装及配置 Git
- 安装参考:https://git-scm.com/download/linux
- 官方说 RHEL 一般自带 Git:RHEL(Red Hat Enterprise Linux) and derivatives typically ship older versions of git.
- 查看 CentOS 是否自带 Git
- rpm 安装的,可以用 rpm -qa 查找。如果要查找某软件包是否安装,用 rpm -qa|grep < packagename >
yum list installed |grep git
git-core-2.27.0-1.el8.x86_64
!!!如果没有返回值则表示没有安装。 - yum 安装的,可以用 yum list installed 查找。如果是查找指定包,命令后加 |grep < packagename >
yum list installed |grep git
git.x86_64 2.27.0-1.el8 @AppStream
!!!如果没有返回值则表示没有安装。 - 如果是用 源码包 编译安装的,例如.tar.gz或者tar.bz2形式的,这个只能看可执行文件是否存在了,上面两种方法都看不到这种源码形式安装的包。
- 如果是以 root 用户安装的,可执行程序通常都在 /sbin/usr/bin 目录下。
- rpm 安装的,可以用 rpm -qa 查找。如果要查找某软件包是否安装,用 rpm -qa|grep < packagename >
- 如果没有安装,用
yum install git
或 用源代码编译安装。 - 配置 Git。配置 Git 的目的是让 Git 知道谁修改了项目,方便 Git 进行版本跟踪。
关于配置 Git 的详细说明: https://git-scm.com/docs/git-config
Git 基本配置:https://training.github.com/downloads/zh_CN/github-git-cheat-sheet/
2. Git 使用流程
-
进行配置
查看配置列表。git config --list
如果之前没有进行任何配置,则直接进入新的命令行。
配置相关的命令。git config
获取所有可选命令。或者查阅参考手册。
参考:对给git配置邮箱和用户名的理解 https://blog.csdn.net/ITWANGBOIT/article/details/103618427git config --global user.name "username" git config --global user.email "username@example.com
-
忽略无需跟踪的文件
参考《Python编程:从入门到实践》附录 D:D.3 忽略文件 -
初始化仓库
在项目文件夹中执行命令git init
。我的项目文件夹是 C:\Users\dell\learning_log(即 manage.py 所在文件夹)。!!!注意,创建的是一个 .git 文件夹,以 . 开头的文件一般会默认隐藏,请用ls -a
查看是否添加成功。 -
检查状态
执行命令git status
-
将文件添加到仓库中
执行命令git add .
!!! 注意,不要忘记句点,每次添加完请用git status
检查一下状态。命令git add .将项目中未被跟踪的所有文件都加入到仓库中,它不提交这些文件,而只是让 Git 开始关注它们。!!!注意,如果你在两次提交之间创建了新文件,可再次执行命令git add .
将这些新文件加入到仓库中。 -
执行提交
执行命令git commit -m ["descriptive message"]
。标志 -m 让 Git 将接下来的消息,(比如,"Started project.")记录到项目的历史记录中。每次提交完请用git status
检查一下状态,有 nothing to commit, working directory clean 则表示提交成功 。 -
查看提交历史
执行命令git log
-
修改后再次提交
执行命令commit -am ["descriptive message"]
。标志 -a 让 Git 将仓库中所有修改了的文件都加入到当前提交中(如果你在两次提交之间创建了新文件,可再次执行命令 git add . 将这些新文件加入到仓库中)。标志 -m 让 Git 在提交历史中记录一条消息。 -
撤销修改(恢复到上一次快照)
命令git checkout
让你能够恢复到以前的任何提交。命令git checkout .
放弃自最后一次提交后所做的所有修改,将项目恢复到最后一次提交的状态。 -
检出以前的提交,删除仓库
参考《Python编程:从入门到实践》附录 D:D.11、D.12
Web 服务器
1. 关于 wsgi 与 asgi
参考文档:https://docs.djangoproject.com/zh-hans/4.0/howto/deployment/
LNMP 和 LAMP 是目前最流行的 Web 应用部署方案,这里的 P 基本是指 PHP ,当然也可以是 Python。常见的 Web 服务器有 Apache Web server、Nginx、Tomcat、Lighttpd...
部署 Django 应用程序有很多选择,可以基于架构或者特定的业务需要选择部署方案。
Django 是一个需要 Web 服务器来运行的 Web 框架。然而由于大多数 Web 服务器不是用 Python 编写的,因此我们需要一个接口来实现沟通。
Django 现在支持两种接口:WSGI 和 ASGI。在项目的 settings.py 所在的目录有 Django 自动生成的 Web 接口脚本,即 wsgi.py 和 asgi.py。
- WSGI 是 Python 的主要接口标准,用于网络服务器和应用程序之间的通信,但它只支持同步代码。
- ASGI 是新兴的、对异步友好的、让 Django Web 应用使用 Python 异步特性的接口标准。
显然,我们的 Django 项目部署需要一个支持 wsgi 或 asgi 的 Web 服务器。支持 wsgi 接口的 Web 服务器通常叫 WSGI 服务器,asgi 同理。
2. 选择 Web 服务器
参考文档:https://docs.djangoproject.com/zh-hans/4.0/howto/deployment/
显然,我们可以按 Django 支持的接口类型选择 Web 服务器,因此,可以选择 WSGI 或 ASGI 进行部署。注意!!!选择以下任一方案中的任一服务器配置即可。
方案一:使用 WSGI 服务器部署
- Gunicorn:UNIX 下的纯 Python WSGI 服务器。
- uWSGI:快速的,自我驱动的,对开发者和系统管理员友好的应用容器服务器,完全由 C 编写。
- Apache + mod_wsgi:mod_wsgi 是一个 Apache 模块,它可以管理任何 Python WSGI 应用,包括 Django。
方案二:使用 ASGI 服务器部署
- Daphne:纯 Python 编写的应用于 UNIX 环境的由 Django 项目维护的 ASGI 服务器。
- Hypercorn:加强支持 HTTP/1,HTTP/2 和 HTTP/3 的 ASGI 服务器。
- Uvicorn:基于 uvloop 和 httptools 的加强运行速度的 ASGI 服务器。
管理与部署静态文件
1. 基础概念
网站通常需要提供类似图片,JavaScript 或 CSS 的额外文件服务。在 Django 中,我们将这些文件称为“静态文件”。Django 提供了 django.contrib.staticfiles 帮你管理它们。
参考文章
- Django 4.0 documentation, 4.17 How to manage static files (e.g. images, JavaScript, CSS)
https://docs.djangoproject.com/zh-hans/4.0/howto/static-files/ - Django 4.0 documentation, 4.18 How to deploy static files
https://docs.djangoproject.com/zh-hans/4.0/howto/static-files/deployment/ - Django 4.0 documentation, 6.5.12 The staticfiles app
https://docs.djangoproject.com/zh-hans/4.0/ref/contrib/staticfiles/
2. 管理静态文件
详细内容参考:Django 4.0 documentation,4.17.1 Configuring static files,此处记录一些笔记。
在创建项目时,Django 在INSTALLED_APPS 里自动添加了 django.contrib.staticfiles 应用。
STATIC_URL = 'static/'
所指的位置是项目根目录中 static 文件的位置,即 learning_log/learning_log/static/,注意!!!我们需要自己手动创建一个 static 文件夹,并在文件夹内创建一个placeholder.txt 文件作为占位符,里面写明这是静态文件所在位置即可(有些部署平台,如 Heroku,会在项目打包上传后会删除空文件夹)。
3. 部署静态文件
详细内容参考:
Django 4.0 documentation,4.17.7 Deployment
Django 4.0 documentation,4.18 How to deploy static files,介绍了三种常见的静态文件部署模式,此处学习其中一种。
无论是管理还是配置静态文件,都没有唯一的固定的方法和流程,具体情况具体分析。但是,了解常规的操作方法总是大有裨益的。
如何在同一服务器运行网站和提供静态文件服务? 操作步骤类似这样:
- 将代码推送至部署服务器。
- 在服务器上运行 collectstatic,将所有的静态文件拷贝至 STATIC_ROOT。
- 配置 Web 服务器,使其在 STATIC_URL 下为 STATIC_ROOT 目录下的文件提供静态文件服务。
Bug 总结
1. 'ajango-admin.py'不是内部或外部命令,也不是可运行的程序或批处理文件。
书中作者是用 MacOS 开发的,我是用 Windows, 此处不用后缀 .py,直接使用 django-admin startproject < projectname >
配置环境变量,此处复制异常参考百度。注意!!!我的 django-admin.py 在 python 虚拟环境文件夹的 \Scripts 文件夹下,不在网络解答说的 \bin 文件夹下。一定要思考解答者的开发环境是否和自己一致。
2. TypeError: ForeignKey.\(\underline{~~}init\underline{~~}()\) missing 1 required positional argument: 'on_delete'
书中位置
P366 18.2.5 迁移模型 Entry
问题描述
终端执行命令(ll_env) C:\Users\dell\learning_log> python manage.py makemigrations learning_logs
后出现 TypeError: ForeignKey.\(\underline{~~}init\underline{~~}()\) missing 1 required positional argument: 'on_delete'
解决方法
先了解一下级联删除,级联删除是指当主表(parent table)中的一条记录被删除,子表中关联的记录也对应的主动删除。
在 Django2.0后,设置多对一关系时,必须要设置级联删除,也就是当你删除主表的记录时,会级联删除所有和这一条记录对应的子表中的多条记录。
< foreignkey_name> = models.ForeignKey(< parent_table >, on_delete=models.CASCADE) # 添加 on_delete=models.CASCADE 参数
新版本指定 on_delete=models.CASCADE 参数就是为了达到级联删除的目的,在老版本这个参数on_delete=models.CASCADE 是默认值。
开发日记
心态与方法
对于新手,《Python编程:入门与实践》这本书第一章到十一章的基础知识部分确实通俗易懂,非常棒。项目一的游戏和项目二的数据可视化也挺好,虽然自己需要扩展 pygame、matplotlib、pygal 的一些知识,但基本不涉及到 Linux 环境下的开发以及项目部署问题,心态上会好很多,对于项目三的 Web 应用开发和部署,我需要学习 Linux 工作环境和项目部署框架,这对于新手而言会比较不友好,所以在做项目三之前我需要做一些准备工作:
(1)简单通读一遍书中的项目开发和部署流程,扫清一些框架和整体认识上的盲点。
(2)注意参考书及软件版本迭代问题造成的开发和部署错误。比如:作者是用 MacOS 终端开发的,我用 Windows开发。
(3)心态一定要好,信念一定要坚定。
还是很喜欢王澍的这段话:一个好的建筑师,就是你一开始有一个很纯粹的、带有理想主义的想法,完了以后你要像长征一样的,经过很多的险阻,中间很多次都有人想摧毁你、否定你,你必须能够做到百折不挠,而且要说服大家。最后走到终点,你还保持了你最初理想的那个纯度,没有半分的减损,甚至更加的坚定,这就是一个好的建筑师。
阅读官方文档
我发现,完全按作者的步骤固然可以完成这个有趣的 Web 项目,但是会留下“十万个为什么”,面对网上大量碎片化而不甚权威的解答,我感到十分恼火,而且很多解答都是作者复制抄袭别人的,所以我决定阅读官方文档。这份完整的官方文档有足足2238页,可供下载的文档只有英文版,中文版只有在线文档,这对我的阅读是个挑战,所以,我必须掌握快速捕捉有用信息的能力,这有助于我提高开发效率。
我不应该抗拒阅读英文文档,因为优秀技术文档的第一手资料都是英文的,如果要获取最新的技术,就必须掌握英文阅读的能力,依赖翻译后的文档永远是落后的。
限制敏感页面的访问
Django 能够轻松地限制对页面的访问,但我们必须确定要保护哪些页面。最好先确定项目的哪些页面不需要保护,再限制对其他所有页面的访问。因为我们可以轻松地修改过于严格的访问限制,比起不限制对敏感页面的访问,这样做的风险更低。