Commit 0640abb2 authored by jackfrued's avatar jackfrued

更新了Linux、数据库和Django部分的文档

parent 87de54a0
This diff is collapsed.
......@@ -498,7 +498,7 @@ python3
```Python
>>> from pymongo import MongoClient
>>> client = MongoClient('mongodb://120.77.222.217:27017')
>>> client = MongoClient('mongodb://127.0.0.1:27017')
>>> db = client.school
>>> for student in db.students.find():
... print('学号:', student['stuid'])
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -12,13 +12,13 @@
2. 隐藏域(隐式表单域)。在提交表单的时候,可以通过在表单中设置隐藏域向服务器发送额外的数据。例如:`<input type="hidden" name="sessionid" value="123456">`
3. Cookie。Cookie是保存在浏览器临时文件中的数据,每次请求时,请求头中会携带本站点的cookie到服务器,那么只要将sessionid写入cookie,下次请求时服务器只要读取请求头中的cookie就能够获得这个sessionid,如下图所示:
3. 本地存储。现在的浏览器都支持多种本地存储方案,包括:cookie、localStorage、sessionStorage、IndexedDB等。在这些方案中,cookie是历史最为悠久也是被诟病得最多的一种方案,也是我们接下来首先为大家讲解的一种方案。简单的说,cookie是一种以键值对方式保存在浏览器临时文件中的数据,每次请求时,请求头中会携带本站点的cookie到服务器,那么只要将sessionid写入cookie,下次请求时服务器只要读取请求头中的cookie就能够获得这个sessionid,如下图所示。
![](./res/sessionid_from_cookie.png)
需要说明的是,在HTML5时代要想在浏览器中保存数据,除了使用cookie之外,还可以使用新的本地存储API,包括localStorage、sessionStorage、IndexedDB等,如下图所示。
在HTML5时代要,除了cookie,还可以使用新的本地存储API来保存数据,就是刚才提到的localStorage、sessionStorage、IndexedDB等技术,如下图所示。
![](./res/cookie_xstorage_indexeddb.png)
![](./res/cookie_xstorage_indexeddb.png)
### Django框架对session的支持
......@@ -57,7 +57,7 @@ def login(request: HttpRequest):
user = User.objects.filter(username=username, password=password).first()
if user:
# 登录成功后将用户编号和用户名保存在session中
request.session['no'] = user.no
request.session['userid'] = user.no
request.session['username'] = user.username
return redirect('/')
else:
......@@ -67,11 +67,11 @@ def login(request: HttpRequest):
return render(request, 'login.html', {'hint': hint})
```
上面的代码中,我们设定了登录成功后会在session中保存用户的编号(`no`)和用户名(`username`),页面会重定向到首页。接下来我们可以稍微对首页的代码进行调整,在页面的右上角显示出登录用户的用户名。我们将这段代码单独写成了一个名为header.html的HTML文件,首页中可以通过在`<body>`标签中添加`{% include 'header.html' %}`来包含这个页面,代码如下所示。
上面的代码中,我们设定了登录成功后会在session中保存用户的编号(`userid`)和用户名(`username`),页面会重定向到首页。接下来我们可以稍微对首页的代码进行调整,在页面的右上角显示出登录用户的用户名。我们将这段代码单独写成了一个名为header.html的HTML文件,首页中可以通过在`<body>`标签中添加`{% include 'header.html' %}`来包含这个页面,代码如下所示。
```HTML
<div class="user">
{% if request.session.no %}
{% if request.session.userid %}
<span>{{ request.session.username }}</span>
<a href="/vote/logout">注销</a>
{% else %}
......@@ -81,7 +81,7 @@ def login(request: HttpRequest):
</div>
```
如果用户没有登录,页面会显示登录和注册的超链接;而用户登录成功后,页面上会显示用户名和注销的链接,注销链接对应的视图函数如下所示。
如果用户没有登录,页面会显示登录和注册的超链接;而用户登录成功后,页面上会显示用户名和注销的链接,注销链接对应的视图函数如下所示,URL的映射与之前讲过的类似,不再赘述
```Python
def logout(request):
......
......@@ -9,7 +9,7 @@ def praise_or_criticize(request: HttpRequest):
try:
tno = int(request.GET.get('tno', '0'))
teacher = Teacher.objects.get(no=tno)
if request.path.startswith('/vote/praise'):
if request.path.startswith('/praise'):
teacher.good_count += 1
else:
teacher.bad_count += 1
......@@ -30,19 +30,14 @@ def praise_or_criticize(request: HttpRequest):
$('.comment > a').on('click', (evt) => {
evt.preventDefault()
let a = $(evt.target)
$.ajax({
url: a.attr('href'),
type: 'get',
dataType: 'json',
success: (json) => {
if (json.code == 200) {
let span = a.next()
span.text(parseInt(span.text()) + 1)
} else if (json.code == 401) {
location.href = '/vote/login/?backurl=' + location.href
} else {
alert(json.message)
}
$.getJSON(a.attr('href'), (json) => {
if (json.code == 200) {
let span = a.next()
span.text(parseInt(span.text()) + 1)
} else if (json.code == 401) {
location.href = '/login/?backurl=' + location.href
} else {
alert(json.message)
}
})
})
......
## 日志和调试
在项目开发阶段,显示足够的调试信息以辅助开发人员调试代码还是非常必要的.
项目开发阶段,显示足够的调试信息以辅助开发人员调试代码还是非常必要的;项目上线以后,将系统运行时出现的警告、错误等信息记录下来以备相关人员了解系统运行状况并维护代码也是很有必要的。要做好这两件事件,我们需要为Django项目配置日志。
### 配置日志
Django的日志配置基本可以参照官方文档再结合项目实际需求来进行,这些内容基本上可以从官方文档上复制下来,然后进行局部的调整即可,下面给出一些参考配置。
```Python
LOGGING = {
'version': 1,
# 是否禁用已经存在的日志器
'disable_existing_loggers': False,
# 日志格式化器
'formatters': {
'simple': {
'format': '%(asctime)s %(module)s.%(funcName)s: %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
'verbose': {
'format': '%(asctime)s %(levelname)s [%(process)d-%(threadName)s] '
'%(module)s.%(funcName)s line %(lineno)d: %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
}
},
# 日志过滤器
'filters': {
# 只有在Django配置文件中DEBUG值为True时才起作用
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
# 日志处理器
'handlers': {
# 输出到控制台
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'filters': ['require_debug_true'],
'formatter': 'simple',
},
# 输出到文件(每周切割一次)
'file1': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': 'access.log',
'when': 'W0',
'backupCount': 12,
'formatter': 'simple',
'level': 'INFO',
},
# 输出到文件(每天切割一次)
'file2': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': 'error.log',
'when': 'D',
'backupCount': 31,
'formatter': 'verbose',
'level': 'WARNING',
},
},
# 日志器记录器
'loggers': {
'django': {
# 需要使用的日志处理器
'handlers': ['console', 'file1', 'file2'],
# 是否向上传播日志信息
'propagate': True,
# 日志级别(不一定是最终的日志级别)
'level': 'DEBUG',
},
}
}
```
大家可能已经注意到了,上面日志配置中的formatters是**日志格式化器**,它代表了如何格式化输出日志,其中格式占位符分别表示:
1. %(name)s - 记录器的名称
2. %(levelno)s - 数字形式的日志记录级别
3. %(levelname)s - 日志记录级别的文本名称
4. %(filename)s - 执行日志记录调用的源文件的文件名称
5. %(pathname)s - 执行日志记录调用的源文件的路径名称
6. %(funcName)s - 执行日志记录调用的函数名称
7. %(module)s - 执行日志记录调用的模块名称
8. %(lineno)s - 执行日志记录调用的行号
9. %(created)s - 执行日志记录的时间
10. %(asctime)s - 日期和时间
11. %(msecs)s - 毫秒部分
12. %(thread)d - 线程ID(整数)
13. %(threadName)s - 线程名称
14. %(process)d - 进程ID (整数)
日志配置中的handlers用来指定**日志处理器**,简单的说就是指定将日志输出到控制台还是文件又或者是网络上的服务器,可用的处理器包括:
1. logging.StreamHandler(stream=None) - 可以向类似与sys.stdout或者sys.stderr的任何文件对象输出信息
2. logging.FileHandler(filename, mode='a', encoding=None, delay=False) - 将日志消息写入文件
3. logging.handlers.DatagramHandler(host, port) - 使用UDP协议,将日志信息发送到指定主机和端口的网络主机上
4. logging.handlers.HTTPHandler(host, url) - 使用HTTP的GET或POST方法将日志消息上传到一台HTTP 服务器
5. logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False) - 将日志消息写入文件,如果文件的大小超出maxBytes指定的值,那么将重新生成一个文件来记录日志
6. logging.handlers.SocketHandler(host, port) - 使用TCP协议,将日志信息发送到指定主机和端口的网络主机上
7. logging.handlers.SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None, timeout=1.0) - 将日志输出到指定的邮件地址
8. logging.MemoryHandler(capacity, flushLevel=ERROR, target=None, flushOnClose=True) - 将日志输出到内存指定的缓冲区中
上面每个日志处理器都指定了一个名为“level”的属性,它代表了日志的级别,不同的日志级别反映出日志中记录信息的严重性。Python中定义了六个级别的日志,按照从低到高的顺序依次是:NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL。
最后配置的**日志记录器**是用来真正输出日志的,Django框架提供了如下所示的内置记录器:
1. django - 在Django层次结构中的所有消息记录器
2. django.request - 与请求处理相关的日志消息。5xx响应被视为错误消息;4xx响应被视为为警告消息
3. django.server - 与通过runserver调用的服务器所接收的请求相关的日志消息。5xx响应被视为错误消息;4xx响应被记录为警告消息;其他一切都被记录为INFO
4. django.template - 与模板渲染相关的日志消息
5. django.db.backends - 有与数据库交互产生的日志消息,如果希望显示ORM框架执行的SQL语句,就可以使用该日志记录器。
日志记录器中配置的日志级别有可能不是最终的日志级别,因为还要参考日志处理器中配置的日志级别,取二者中级别较高者作为最终的日志级别。
### 配置Django-Debug-Toolbar
Django-Debug-Toolbar是辅助Django项目开发的神器,只要配置了它,就可以很方便的查看到以下内容,这些信息对了解项目的运行状况以及优化Web应用性能都是至关重要的。
| 项目 | 说明 |
| ----------- | --------------------------------- |
| Versions | Django的版本 |
| Time | 显示视图耗费的时间 |
| Settings | 配置文件中设置的值 |
| Headers | HTTP请求头和响应头的信息 |
| Request | 和请求相关的各种变量及其信息 |
| StaticFiles | 静态文件加载情况 |
| Templates | 模板的相关信息 |
| Cache | 缓存的使用情况 |
| Signals | Django内置的信号信息 |
| Logging | 被记录的日志信息 |
| SQL | 向数据库发送的SQL语句及其执行时间 |
1. 安装Django-Debug-Toolbar。
```Shell
pip install django-debug-toolbar
```
2. 配置 - 修改settings.py。
```Python
INSTALLED_APPS = [
'debug_toolbar',
]
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
DEBUG_TOOLBAR_CONFIG = {
# 引入jQuery库
'JQUERY_URL': 'https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js',
# 工具栏是否折叠
'SHOW_COLLAPSED': True,
# 是否显示工具栏
'SHOW_TOOLBAR_CALLBACK': lambda x: True,
}
```
3. 配置 - 修改urls.py。
```Python
if settings.DEBUG:
import debug_toolbar
urlpatterns.insert(0, path('__debug__/', include(debug_toolbar.urls)))
```
4. 使用 - 在页面右侧可以看到一个调试工具栏,上面包括了如前所述的调试信息,包括:执行时间、项目设置、请求头、SQL、静态资源、模板、缓存、信号等,查看起来非常的方便。
\ No newline at end of file
......@@ -182,7 +182,7 @@ ipython最直观的优点:
resp = requests.get('http://api.tianapi.com/allnews/?key=请使用自己申请的Key&col=7&num=50')
```
> 说明:上面使用了天行数据提供的数据接口,需要的话可以自行去[天行数据](<https://www.tianapi.com/>)的网站注册开通。
> 说明:上面使用了天行数据提供的数据接口,需要的话可以自行去[天行数据](<https://www.tianapi.com/>)的网站注册开通,调用接口的时候要填写注册成功后系统分配给你的key
3. 使用反序列化将JSON字符串解析为字典并获取新闻列表。
......@@ -225,5 +225,5 @@ ipython最直观的优点:
)
```
> 说明:上面的代码使用了[螺丝帽](<https://luosimao.com/>)的短信网关,利用短信网关发送短信是需要支付费用的,但是一般的平台都会提供免费测试的短信,但是发送短信必须遵守平台的规则,违规的短信是无法发送的。上面发短信时使用的短信模板(“发现一条您可能感兴趣的新闻 - ###,详情点击https://news.china.com/### 查看。”)和短信签名(“【Python小课】”)需要登录螺丝帽管理平台进行配置,如果不清楚如何配置,这些平台都是有客服的哟
> 说明:上面的代码使用了[螺丝帽](<https://luosimao.com/>)提供的短信网关服务,利用短信网关发送短信是需要支付费用的,但是一般的平台都会提供若干条免费的测试短信。发送短信必须遵守平台的规则,违规的短信是无法发送的。上面发短信时使用的短信模板(“发现一条您可能感兴趣的新闻 - ###,详情点击https://news.china.com/### 查看。”)和短信签名(“【Python小课】”)需要登录螺丝帽管理平台进行配置,如果不清楚如何配置,可以联系平台的客服人员进行咨询
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