Skip to content

Commit

Permalink
更新了Django部分的文档
Browse files Browse the repository at this point in the history
  • Loading branch information
jackfrued committed Jun 18, 2019
1 parent 0640abb commit 0ab0d99
Show file tree
Hide file tree
Showing 18 changed files with 252 additions and 177 deletions.
211 changes: 91 additions & 120 deletions Day41-55/43.静态资源和Ajax请求.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Day41-55/45.Cookie和Session.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>
```

Expand Down
64 changes: 60 additions & 4 deletions Day41-55/47.日志和调试.md → Day41-55/46.报表和日志.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,65 @@
## 日志和调试
## 报表和日志

###导出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
Expand Down Expand Up @@ -114,7 +170,7 @@ LOGGING = {

### 配置Django-Debug-Toolbar

Django-Debug-Toolbar是辅助Django项目开发的神器,只要配置了它,就可以很方便的查看到以下内容,这些信息对了解项目的运行状况以及优化Web应用性能都是至关重要的
Django-Debug-Toolbar是项目开发阶段辅助调试和优化的神器,只要配置了它,就可以很方便的查看到如下表所示的项目运行信息,这些信息对调试项目和优化Web应用性能都是至关重要的

| 项目 | 说明 |
| ----------- | --------------------------------- |
Expand Down Expand Up @@ -167,4 +223,4 @@ Django-Debug-Toolbar是辅助Django项目开发的神器,只要配置了它,
urlpatterns.insert(0, path('__debug__/', include(debug_toolbar.urls)))
```
4. 使用 - 在页面右侧可以看到一个调试工具栏,上面包括了如前所述的调试信息,包括:执行时间、项目设置、请求头、SQL、静态资源、模板、缓存、信号等,查看起来非常的方便。
4. 使用 - 如下图所示,在配置好Django-Debug-Toolbar之后,页面右侧会看到一个调试工具栏,上面包括了如前所述的各种调试信息,包括执行时间、项目设置、请求头、SQL、静态资源、模板、缓存、信号等,查看起来非常的方便。
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## 中间件的应用

### 实现登录验证

我们继续来完善投票应用。在上一个章节中,我们在用户登录成功后通过session保留了用户信息,接下来我们可以应用做一些调整,要求在为老师投票时必须要先登录,登录过的用户可以投票,否则就将用户引导到登录页面,为此我们可以这样修改视图函数。

```Python
Expand Down Expand Up @@ -47,7 +49,7 @@ def praise_or_criticize(request: HttpRequest):

> 注意:为了在登录成功之后能够回到刚才投票的页面,我们在跳转登录时设置了一个`backurl`参数,把当前浏览器中的URL作为返回的页面地址。
这样我们已经实现了用户必须登录才能投票的限制,但是一个新的问题来了。如果我们的应用中有很多功能都需要用户先登录才能执行,那么我们是不是需要在每个视图函数中添加代码来检查session中是否包含了登录用户的信息呢?答案是否定的,如果这样做了,我们的视图函数中必然会充斥着大量的重复代码。编程大师*Martin Fowler*曾经说过:**代码有很多种坏味道,重复是最坏的一种**我们可以把验证用户是否登录这样的代码放到Django的中间件中
这样我们已经实现了用户必须登录才能投票的限制,但是一个新的问题来了。如果我们的应用中有很多功能都需要用户先登录才能执行,例如将前面导出Excel报表和查看统计图表的功能都加以登录限制,那么我们是不是需要在每个视图函数中添加代码来检查session中是否包含了登录用户的信息呢?答案是否定的,如果这样做了,我们的视图函数中必然会充斥着大量的重复代码。编程大师*Martin Fowler*曾经说过:**代码有很多种坏味道,重复是最坏的一种**在Django项目中,我们可以把验证用户是否登录这样的重复性代码放到中间件中

### Django中间件概述

Expand Down Expand Up @@ -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
```
Expand All @@ -128,3 +141,6 @@ MIDDLEWARE = [
]
```

注意上面这个中间件列表中元素的顺序,当收到来自用户的请求时,中间件按照从上到下的顺序依次执行,这行完这些中间件以后,请求才会最终到达视图函数。当然,在这个过程中,用户的请求可以被拦截,就像上面我们自定义的中间件那样,如果用户在没有登录的情况下访问了受保护的资源,中间件会将请求直接重定向到登录页,后面的中间件和视图函数将不再执行。在响应用户请求的过程中,上面的中间件会按照从下到上的顺序依次执行,这样的话我们还可以对响应做进一步的处理。

中间件执行的顺序是非常重要的,对于有依赖关系的中间件必须保证被依赖的中间件要置于依赖它的中间件的前面,就好比我们刚才自定义的中间件要放到`SessionMiddleware`的后面,因为我们要依赖这个中间件为请求绑定的`session`对象才能判定用户是否登录。
2 changes: 2 additions & 0 deletions Day41-55/48.前后端分离开发.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
## 前后端分离开发

File renamed without changes.
4 changes: 0 additions & 4 deletions Day41-55/49.文件下载和报表.md

This file was deleted.

File renamed without changes.
File renamed without changes.
Binary file removed Day41-55/res/show-subjects.png
Binary file not shown.
Binary file removed Day41-55/res/show-teachers.png
Binary file not shown.
Binary file added Day41-55/res/show_subjects.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Day41-55/res/show_teachers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion Day66-75/66.网络爬虫和相关工具.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## 网络爬虫和相关工具

### 网络爬虫
### 网络爬虫的概念

网络爬虫(web crawler),以前经常称之为网络蜘蛛(spider),是按照一定的规则自动浏览万维网并获取信息的机器人程序(或脚本),曾经被广泛的应用于互联网搜索引擎。使用过互联网和浏览器的人都知道,网页中除了供用户阅读的文字信息之外,还包含一些超链接。网络爬虫系统正是通过网页中的超链接信息不断获得网络上的其它页面。正因如此,网络数据采集的过程就像一个爬虫或者蜘蛛在网络上漫游,所以才被形象的称为网络爬虫或者网络蜘蛛。

Expand Down
Loading

0 comments on commit 0ab0d99

Please sign in to comment.