Commit 0ab0d997 authored by jackfrued's avatar jackfrued

更新了Django部分的文档

parent 0640abb2
This diff is collapsed.
......@@ -73,11 +73,11 @@ def login(request: HttpRequest):
<div class="user">
{% if request.session.userid %}
<span>{{ request.session.username }}</span>
<a href="/vote/logout">注销</a>
<a href="/logout">注销</a>
{% else %}
<a href="/vote/login">登录</a>&nbsp;&nbsp;
<a href="/login">登录</a>&nbsp;&nbsp;
{% endif %}
<a href="/vote/register">注册</a>
<a href="/register">注册</a>
</div>
```
......
## 日志和调试
## 报表和日志
###导出Excel报表
报表就是用表格、图表等格式来动态显示数据,所以有人用这样的公式来描述报表:
```
报表 = 多样的格式 + 动态的数据
```
有很多的三方库支持在Python程序中写Excel文件,包括[xlwt](<https://xlwt.readthedocs.io/en/latest/>)[xlwings](<https://docs.xlwings.org/en/latest/quickstart.html>)[openpyxl](<https://openpyxl.readthedocs.io/en/latest/>)[xlswriter](<https://xlsxwriter.readthedocs.io/>)[pandas](<http://pandas.pydata.org/>)等,其中的xlwt虽然只支持写xls格式的Excel文件,但在性能方面的表现还是不错的。下面我们就以xlwt为例,来演示如何在Django项目中导出Excel报表,例如导出一个包含所有老师信息的Excel表格。
```Python
def export_teachers_excel(request):
# 创建工作簿
wb = xlwt.Workbook()
# 添加工作表
sheet = wb.add_sheet('老师信息表')
# 查询所有老师的信息(注意:这个地方稍后需要优化)
queryset = Teacher.objects.all()
# 向Excel表单中写入表头
colnames = ('姓名', '介绍', '好评数', '差评数', '学科')
for index, name in enumerate(colnames):
sheet.write(0, index, name)
# 向单元格中写入老师的数据
props = ('name', 'detail', 'good_count', 'bad_count', 'subject')
for row, teacher in enumerate(queryset):
for col, prop in enumerate(props):
value = getattr(teacher, prop, '')
if isinstance(value, Subject):
value = value.name
sheet.write(row + 1, col, value)
# 保存Excel
buffer = BytesIO()
wb.save(buffer)
# 将二进制数据写入响应的消息体中并设置MIME类型
resp = HttpResponse(buffer.getvalue(), content_type='application/vnd.ms-excel')
# 中文文件名需要处理成百分号编码
filename = quote('老师.xls')
# 通过响应头告知浏览器下载该文件以及对应的文件名
resp['content-disposition'] = f'attachment; filename="{filename}"'
return resp
```
映射URL。
```Python
urlpatterns = [
# 此处省略上面的代码
path('excel/', views.export_teachers_excel),
# 此处省略下面的代码
]
```
### 生成前端统计图表
项目开发阶段,显示足够的调试信息以辅助开发人员调试代码还是非常必要的;项目上线以后,将系统运行时出现的警告、错误等信息记录下来以备相关人员了解系统运行状况并维护代码也是很有必要的。要做好这两件事件,我们需要为Django项目配置日志。
### 配置日志
项目开发阶段,显示足够的调试信息以辅助开发人员调试代码还是非常必要的;项目上线以后,将系统运行时出现的警告、错误等信息记录下来以备相关人员了解系统运行状况并维护代码也是很有必要的。要做好这两件事件,我们需要为Django项目配置日志。
Django的日志配置基本可以参照官方文档再结合项目实际需求来进行,这些内容基本上可以从官方文档上复制下来,然后进行局部的调整即可,下面给出一些参考配置。
```Python
......@@ -114,7 +170,7 @@ LOGGING = {
### 配置Django-Debug-Toolbar
Django-Debug-Toolbar是辅助Django项目开发的神器,只要配置了它,就可以很方便的查看到以下内容,这些信息对了解项目的运行状况以及优化Web应用性能都是至关重要的。
Django-Debug-Toolbar是项目开发阶段辅助调试和优化的神器,只要配置了它,就可以很方便的查看到如下表所示的项目运行信息,这些信息对调试项目和优化Web应用性能都是至关重要的。
| 项目 | 说明 |
| ----------- | --------------------------------- |
......@@ -167,4 +223,4 @@ Django-Debug-Toolbar是辅助Django项目开发的神器,只要配置了它,
urlpatterns.insert(0, path('__debug__/', include(debug_toolbar.urls)))
```
4. 使用 - 在页面右侧可以看到一个调试工具栏,上面包括了如前所述的调试信息,包括:执行时间、项目设置、请求头、SQL、静态资源、模板、缓存、信号等,查看起来非常的方便。
\ No newline at end of file
4. 使用 - 如下图所示,在配置好Django-Debug-Toolbar之后,页面右侧会看到一个调试工具栏,上面包括了如前所述的各种调试信息,包括执行时间、项目设置、请求头、SQL、静态资源、模板、缓存、信号等,查看起来非常的方便。
\ No newline at end of file
## 中间件的应用
### 实现登录验证
我们继续来完善投票应用。在上一个章节中,我们在用户登录成功后通过session保留了用户信息,接下来我们可以应用做一些调整,要求在为老师投票时必须要先登录,登录过的用户可以投票,否则就将用户引导到登录页面,为此我们可以这样修改视图函数。
```Python
......@@ -47,7 +49,7 @@ def praise_or_criticize(request: HttpRequest):
> 注意:为了在登录成功之后能够回到刚才投票的页面,我们在跳转登录时设置了一个`backurl`参数,把当前浏览器中的URL作为返回的页面地址。
这样我们已经实现了用户必须登录才能投票的限制,但是一个新的问题来了。如果我们的应用中有很多功能都需要用户先登录才能执行,那么我们是不是需要在每个视图函数中添加代码来检查session中是否包含了登录用户的信息呢?答案是否定的,如果这样做了,我们的视图函数中必然会充斥着大量的重复代码。编程大师*Martin Fowler*曾经说过:**代码有很多种坏味道,重复是最坏的一种**。我们可以把验证用户是否登录这样的代码放到Django的中间件中。
这样我们已经实现了用户必须登录才能投票的限制,但是一个新的问题来了。如果我们的应用中有很多功能都需要用户先登录才能执行,例如将前面导出Excel报表和查看统计图表的功能都加以登录限制,那么我们是不是需要在每个视图函数中添加代码来检查session中是否包含了登录用户的信息呢?答案是否定的,如果这样做了,我们的视图函数中必然会充斥着大量的重复代码。编程大师*Martin Fowler*曾经说过:**代码有很多种坏味道,重复是最坏的一种**。在Django项目中,我们可以把验证用户是否登录这样的重复性代码放到中间件中。
### Django中间件概述
......@@ -88,26 +90,37 @@ MIDDLEWARE = [
### 自定义中间件
Django中的中间件有两种实现方式:基于类的实现方式和基于函数的实现方式,后者更接近于装饰器的写法。装饰器实际上是代理模式的应用,将横切关注功能(与正常业务逻辑没有必然联系的功能,例如:身份认证、日志记录、编码转换之类的功能)置于代理中,由代理对象来完成被代理对象的行为并添加额外的功能。中间件对用户请求和响应进行拦截过滤并增加额外的处理,在这一点上它跟装饰器是完全一致的,所以基于函数的写法来实现中间件就跟装饰器的写法几乎一模一样。下面我们用自定义的中间件来实现对用户进行登录验证的功能。
Django中的中间件有两种实现方式:基于类的实现方式和基于函数的实现方式,后者更接近于装饰器的写法。装饰器实际上是代理模式的应用,将横切关注功能(与正常业务逻辑没有必然联系的功能,例如:身份认证、日志记录、编码转换之类的功能)置于代理中,由代理对象来完成被代理对象的行为并添加额外的功能。中间件对用户请求和响应进行拦截过滤并增加额外的处理,在这一点上它跟装饰器是完全一致的,所以基于函数的写法来实现中间件就跟装饰器的写法几乎一模一样。下面我们用自定义的中间件来实现用户登录验证的功能。
```Python
"""
middlewares.py
"""
from django.http import JsonResponse
from django.shortcuts import redirect
# 需要登录才能访问的资源路径
LOGIN_REQUIRED_URLS = {
'/praise/', '/criticize/', '/pdf/', '/excel/',
}
def check_login_middleware(func):
def check_login_middleware(get_resp):
def wrapper(request, *args, **kwargs):
# 获取请求的资源路径
path = request.path
# 如果请求的资源路径在设定的元组中就表示需要登录验证
if path in ('/vote/praise/', '/vote/criticize/'):
if 'username' not in request.session:
# session中没有username就重定向到登录页
return redirect('login')
return func(request, *args, **kwargs)
# 请求的资源路径在上面的集合中
if request.path in LOGIN_REQUIRED_URLS:
# 会话中包含userid则视为已经登录
if 'userid' not in request.session:
# 判断是不是Ajax请求
if request.is_ajax():
# Ajax请求返回JSON数据提示用户登录
return JsonResponse({'code': 10003, 'hint': '请先登录'})
else:
backurl = request.get_full_path()
# 非Ajax请求直接重定向到登录页
return redirect(f'/login/?backurl={backurl}')
return get_resp(request, *args, **kwargs)
return wrapper
```
......@@ -128,3 +141,6 @@ MIDDLEWARE = [
]
```
注意上面这个中间件列表中元素的顺序,当收到来自用户的请求时,中间件按照从上到下的顺序依次执行,这行完这些中间件以后,请求才会最终到达视图函数。当然,在这个过程中,用户的请求可以被拦截,就像上面我们自定义的中间件那样,如果用户在没有登录的情况下访问了受保护的资源,中间件会将请求直接重定向到登录页,后面的中间件和视图函数将不再执行。在响应用户请求的过程中,上面的中间件会按照从下到上的顺序依次执行,这样的话我们还可以对响应做进一步的处理。
中间件执行的顺序是非常重要的,对于有依赖关系的中间件必须保证被依赖的中间件要置于依赖它的中间件的前面,就好比我们刚才自定义的中间件要放到`SessionMiddleware`的后面,因为我们要依赖这个中间件为请求绑定的`session`对象才能判定用户是否登录。
\ No newline at end of file
## 网络爬虫和相关工具
### 网络爬虫
### 网络爬虫的概念
网络爬虫(web crawler),以前经常称之为网络蜘蛛(spider),是按照一定的规则自动浏览万维网并获取信息的机器人程序(或脚本),曾经被广泛的应用于互联网搜索引擎。使用过互联网和浏览器的人都知道,网页中除了供用户阅读的文字信息之外,还包含一些超链接。网络爬虫系统正是通过网页中的超链接信息不断获得网络上的其它页面。正因如此,网络数据采集的过程就像一个爬虫或者蜘蛛在网络上漫游,所以才被形象的称为网络爬虫或者网络蜘蛛。
......
......@@ -2,9 +2,9 @@
> 作者:骆昊
>
> 说明:最近有很多想学习Python的小伙伴申请单独加我微信和QQ,因为我自己平时也很忙,没办法一一解答大家的问题,我创建了**Python100天学习交流5群**(之前的两个2000人群1群和2群、两个1000人群3群和4群已经全部满员),群号为**818146347**,二维码在下方。我的同事和朋友很多也在这个群里,他们都是优秀的Python开发者,有丰富的商业项目经验,我们在时间充足的时候会及时解答大家的问题,而且从Python语言入门到Web应用开发,从数据分析到机器学习,每个领域都有技术大咖为大家解惑答疑。以后我们争取每周做一次视频直播,以专题的形式分享Python开发的点点滴滴,同时还会不定期的举办线上和线下的技术交流和分享活动,小伙伴们可以加群进行交流。感谢**千锋教育Python教学部**对本群的支持。
> 说明:最近有很多想学习Python的小伙伴申请单独加我微信和QQ,因为我自己平时也很忙,没办法一一解答大家的问题,我创建了**Python100天学习交流5群**(之前的两个2000人群1群和2群、两个1000人群3群和4群已经全部满员),群号为**818146347**,二维码在下方。我的同事和朋友也在这个群里,他们很多都是优秀的Python开发者,有丰富的商业项目经验,我们在时间充足的时候会及时解答大家的问题,从Python语言入门到Web应用开发,从数据分析到机器学习,每个领域都有技术大咖为大家解惑答疑。以后我们争取每周做一次视频直播,以专题的形式分享Python开发的点点滴滴,同时还会不定期的举办线上和线下的技术交流和分享活动,小伙伴们可以加群进行交流。创作不易,感谢各位小伙伴的打赏支持,也感谢**千锋教育Python教学部**对QQ群的支持。
![](./res/qq_group.png)
![](./res/python_100_days_qq_group.png)
### Python应用领域和就业形势分析
......@@ -55,7 +55,7 @@
- Python简介 - Python的历史 / Python的优缺点 / Python的应用领域
- 搭建编程环境 - Windows环境 / Linux环境 / MacOS环境
- 从终端运行Python程序 - DOS命令 / Hello, world / print函数 / 运行程序
- 从终端运行Python程序 - Hello, world / print函数 / 运行程序
- 使用IDLE - 交互式环境(REPL) / 编写多行代码 / 运行程序 / 退出IDLE
- 注释 - 注释的作用 / 单行注释 / 多行注释
......@@ -138,13 +138,12 @@
- 写文件 - 覆盖写入 / 追加写入 / 文本文件 / 二进制文件
- 异常处理 - 异常机制的重要性 / try-except代码块 / else代码块 / finally代码块 / 内置异常类型 / 异常栈 / raise语句
- 数据持久化 - CSV文件概述 / csv模块的应用 / JSON数据格式 / json模块的应用
- 综合案例 - 歌词解析
#### Day12 - [字符串和正则表达式](./Day01-15/12.字符串和正则表达式.md)
- 字符串高级操作 - 转义字符 \ 原始字符串 \ 多行字符串 \ in和 not in运算符 \ is开头的方法 \ join和split方法 \ strip相关方法 \ pyperclip模块 \ 不变字符串和可变字符串 \ StringIO的使用
- 正则表达式入门 - 正则表达式的作用 \ 元字符 \ 转义 \ 量词 \ 分组 \ 零宽断言 \贪婪匹配与惰性匹配懒惰 \ 使用re模块实现正则表达式操作(匹配、搜索、替换、捕获)
- 使用正则表达式 - re模块 \ compile函数 \ group和groups方法 \ match方法 \ search方法 \ findall和finditer方法 \ sub和subn方法 \ split方法
- 字符串高级操作 - 转义字符 / 原始字符串 / 多行字符串 / in和 not in运算符 / is开头的方法 / join和split方法 / strip相关方法 / pyperclip模块 / 不变字符串和可变字符串 / StringIO的使用
- 正则表达式入门 - 正则表达式的作用 / 元字符 / 转义 / 量词 / 分组 / 零宽断言 /贪婪匹配与惰性匹配懒惰 / 使用re模块实现正则表达式操作(匹配、搜索、替换、捕获)
- 使用正则表达式 - re模块 / compile函数 / group和groups方法 / match方法 / search方法 / findall和finditer方法 / sub和subn方法 / split方法
- 应用案例 - 使用正则表达式验证输入的字符串
#### Day13 - [进程和线程](./Day01-15/13.进程和线程.md)
......@@ -156,13 +155,11 @@
#### Day14 - [网络编程入门和网络应用开发](./Day01-15/14.网络编程入门和网络应用开发.md)
- 计算机网络基础 - 计算机网络发展史 / “TCP-IP”模型 / IP地址 / 端口 / 协议 / 其他相关概念
- 网络应用架构 - “客户端-服务器”架构 / “浏览器-服务器”架构
- 网络应用模式 - “客户端-服务器”模式 / “浏览器-服务器”模式
- 基于HTTP协议访问网络资源 - 网络API概述 / 访问URL / requests模块 / 解析JSON格式数据
- Python网络编程 - 套接字的概念 / socket模块 / socket函数 / 创建TCP服务器 / 创建TCP客户端 / 创建UDP服务器 / 创建UDP客户端 / SocketServer模块
- 访问网络API - 网络API概述 / 访问URL / requests模块 / 解析JSON格式数据
- 文件传输 - FTP协议 / ftplib模块 / 交互式FTP应用
- 电子邮件 - SMTP协议 / POP3协议 / IMAP协议 / smtplib模块 / poplib模块 / imaplib模块
- 短信服务 - twilio模块 / 国内的短信服务
- 短信服务 - 调用短信服务网关
#### Day15 - [图像和文档处理](./Day01-15/15.图像和办公文档处理.md)
......@@ -256,37 +253,28 @@
- Django框架对session的支持
- 视图函数中的cookie读写操作
#### Day46 - [中间件的应用](./Day41-55/46.中间件的应用.md)
- 什么是中间件
- Django框架内置的中间件
- 自定义中间件及其应用场景
#### Day47 - [日志和调试](./Day41-55/47.日志和调试.md)
- 配置日志
- 配置和使用Django-Debug-Toolbar
#### Day48 - [文件上传和富文本编辑](./Day41-55/48.文件上传.md)
- 文件上传表单控件和图片文件预览
- 服务器端如何处理上传的文件
- 富文本编辑器概述
- wangEditor的使用
#### Day49 - [文件下载和报表](./Day41-55/49.文件下载和报表.md)
#### Day46 - [报表和日志](./Day41-55/46.报表和日志.md)
- 通过HttpResponse修改响应头
- 使用StreamingHttpResponse处理大文件
- 使用xlwt生成Excel报表
- 使用reportlab生成PDF报表
- 使用ECharts生成前端图表
- 配置日志和Django-Debug-Toolbar
#### Day47 - [中间件的应用](./Day41-55/47.中间件的应用.md)
- 什么是中间件
- Django框架内置的中间件
- 自定义中间件及其应用场景
#### Day48 - [全后端分离开发](./Day41-55/48.前后端分离开发.md)
#### Day50 - [RESTful架构和DRF入门](./Day41-55/50.RESTful架构和DRF入门.md)
#### Day49 - [RESTful架构和DRF入门](./Day41-55/49.RESTful架构和DRF入门.md)
#### Day51 - [RESTful架构和DRF进阶](./Day41-55/51.RESTful架构和DRF进阶.md)
#### Day50 - [RESTful架构和DRF进阶](./Day41-55/50.RESTful架构和DRF进阶.md)
#### Day52 - [使用缓存](./Day41-55/52.使用缓存.md)
#### Day51 - [使用缓存](./Day41-55/51.使用缓存.md)
- 网站优化第一定律
......@@ -295,6 +283,13 @@
- 使用装饰器实现页面缓存
- 为数据接口提供缓存服务
#### Day52 - [文件上传和富文本编辑](./Day41-55/52.文件上传.md)
- 文件上传表单控件和图片文件预览
- 服务器端如何处理上传的文件
- 富文本编辑器概述
- wangEditor的使用
#### Day53 - [短信和邮件](./Day41-55/53.短信和邮件.md)
- 常用短信网关平台介绍
......@@ -366,24 +361,63 @@
#### Day66 - [网络爬虫和相关工具](./Day66-75/66.网络爬虫和相关工具.md)
- 网络爬虫的概念及其应用领域
- 网络爬虫的合法性探讨
- 开发网络爬虫的相关工具
- 一个爬虫程序的构成
#### Day67 - [数据采集和解析](./Day66-75/67.数据采集和解析.md)
- 数据采集的标准和三方库
- 页面解析的三种方式:正则表达式解析 / XPath解析 / CSS选择器解析
#### Day68 - [存储数据](./Day66-75/68.存储数据.md)
- 如何存储海量数据
- 实现数据的缓存
#### Day69 - [并发下载](./Day66-75/69.并发下载.md)
- 多线程和多进程
- 异步I/O和协程
- async和await关键字的使用
- 三方库aiohttp的应用
#### Day70 - [解析动态内容](./Day66-75/70.解析动态内容.md)
- JavaScript逆向工程
- 使用Selenium获取动态内容
#### Day71 - [表单交互和验证码处理](./Day66-75/71.表单交互和验证码处理.md)
- 自动提交表单
- Cookie池的应用
- 验证码处理
#### Day72 - [Scrapy入门](./Day66-75/72.Scrapy入门.md)
- Scrapy爬虫框架概述
- 安装和使用Scrapy
#### Day73 - [Scrapy高级应用](./Day66-75/73.Scrapy高级应用.md)
- Spider的用法
- 中间件的应用:下载中间件 / 蜘蛛中间件
- Scrapy对接Selenium抓取动态内容
- Scrapy部署到Docker
#### Day74 - [Scrapy分布式实现](./Day66-75/74.Scrapy分布式实现.md)
- 分布式爬虫的原理
- Scrapy分布式实现
- 使用Scrapyd实现分布式部署
#### Day75 - [爬虫项目实战](./Day66-75/75.爬虫项目实战.md)
- 爬取招聘网站数据
- 爬取房地产行业数据
- 爬取二手车交易平台数据
### Day76~90 - [数据处理和机器学习](./Day76-90)
#### Day76 - [机器学习基础](./Day76-90/76.机器学习基础.md)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment