什么是缓存?
缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存
视图渲染有一定成本,数据库的频繁查询过高;所以对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数;用户拿到响应的时间成本会更低
缓存案例:
from django.shortcuts import renderdef index(request):
- 转自官网
given a URL, try finding that page in the cacheif the page is in the cache: return the cached pageelse: generate the page save the generated page in the cache (for next time) return the generated pageCopy
使用缓存场景:
场景特点:缓存的地方,数据变动频率较少
Django 中缓存配置
- Django中提供多种缓存方式,如需使用需要在
settings.py
中进行配置
Django可以将缓存的数据存储在您的数据库中
说明:
- 尽管存储介质没有更换,但是当把一次负责查询的结果直接存储到表里,比如多个条件的过滤查询结果,可避免重复进行复杂查询,提升效率;
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'my_cache_table', 'TIMEOUT': 300,
python3 manage.py createcachetableCopy
数据缓存到服务器内存中
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'unique-snowflake' }}Copy
将缓存的数据存储到本地文件中
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/var/tmp/django_cache',
Django 中使用缓存
from django.views.decorators.cache import cache_page
from django.views.decorators.cache import cache_pageurlpatterns = [ path('foo/', cache_page(60)(my_view) ),]Copy
from django.shortcuts import render
def index(request):
# 时间复杂度极高的渲染
book_list = Book.objects.all() # -> 此处假设耗时 2s
return render(request, 'index.html', local())
Copy
先引入 cache 对象
方式一:使用 caches['CACHE配置key']
导入具体对象
from django.core.cache import caches
cache1 = caches['myalias']
cache2 = caches['myalias_2']
Copy
方式2 :直接引入 CACHES配置项中的 'default'
项
默认配置引入【指的配置中的default项】 等同于 caches['default']
from django.core.cache import cache
Copy
1. cache.set(key, value, timeout) - 存储缓存
常规命令 set
key: 字符串类型
value: Python对象
timeout:缓存存储时间 默认值为settings.py CACHES对应配置的TIMEOUT
返回值:None
cache.set('my_key', 'myvalue', 30)
Copy
2. cache.get(key) - 获取缓存
常规命令 get
返回值:为key的具体值,如果没有数据,则返回None
cache.get('my_key')
可添加默认值,如果没取到返回默认值
cache.get('my_key', 'default值')
Copy
3.cache.add(key, value) - 存储缓存
常规命令 add 只有在key不存在的时候 才能设置成功
返回值 True or False
cache.add('my_key', 'value') # 如果my_key已经存在,则此次赋值失效
Copy
4. cache.get_or_set(key, value, timeout)
常规命令 get_or_set 如果未获取到数据 则执行set操作
返回值 key的值
cache.get_or_set('my_key', 'value', 10)
Copy
5. cache.set_many(dict,timeout) - 批量存储缓存
6. cache.get_many(key_list) - 批量获取缓存数据
常规命令 get_many(key_list) set_many(dict,timeout)
返回值:
set_many:返回插入不成功的key数组
get_many:取到的key和value的字典
>>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}
Copy
7. cache.delete(key) - 删除key的缓存数据
常规命令 delete
返回值 None
cache.delete('my_key')
Copy
8. cache.delete_many(key_list) - 批量删除
常规命令 delete_many
返回值 成功删除的数据条数
cache.delete_many(['a', 'b', 'c'])
Copy
浏览器中缓存策略
浏览器也具备缓存技术,对于浏览器来说,每次向服务器发出请求都是耗时的操作,如果本身浏览器内部就具备当前 url 的内容,则一定时间内可以不必给服务器发消息,从而提升网民体验,降低服务器请求压力
不会向服务器发送请求,直接从缓存中读取资源
1. 响应头 - Expires
- 定义:缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点
- 样例:Expires:Thu, 02 Apr 2030 05:14:08 GMT
2. 响应头 - Cache-Control
在HTTP/1.1中,Cache-Control主要用于控制网页缓存。比如当 Cache-Control:max-age=120
代表请求创建时间后的120秒,缓存失效
说明:目前服务器都会带着这两个头同时响应给浏览器,浏览器优先使用 Cache-Control
强缓存中的数据一旦过期,还需要跟服务器进行通信,从而获取最新数据;
思考?如果强缓存的数据是一些静态文件,大图片等;
解答:考虑到大图片这类比较费带宽且不易变化的数据,强缓存时间到期后,浏览器会去跟服务器协商,当前缓存是否可用,如果可用,服务器不必返回数据,浏览器继续使用原来缓存的数据,如果文件不可用,则返回最新数据
1. Last-Modified响应头 和 If-Modified-Since请求头
说明:
2. ETag响应头 和 If-None-Match请求头
说明:
- 精度不一样 – Etag准确率更高
- 性能上 – Last-Modified 高, Etag需要计算文件标识
-
优先级 – Etag 高;两个头同时出现,浏览器优先取Etag
-
中间件是 Django 请求/响应处理的钩子框架。它是一个轻量级的、低级的”插件”系统,用于全局改变 Django 的输入或输出。
- 中间件以类的形式体现
- 每个中间件组件负责做一些特定的功能。例如,Django 包含一个中间件组件
AuthenticationMiddleware
,它使用会话将用户与请求关联起来。
编写中间件类
- 中间件类须继承自
django.utils.deprecation.MiddlewareMixin
类 - 中间件类须实现下列五个方法中的一个或多个:
def process_request(self, request):
执行路由之前被调用,在每个请求上调用,返回None或HttpResponse对象def process_view(self, request, callback, callback_args, callback_kwargs):
调用视图之前被调用,在每个请求上调用,返回None或HttpResponse对象def process_response(self, request, response):
所有响应返回浏览器 被调用,在每个请求上调用,返回HttpResponse对象def process_exception(self, request, exception):
当处理过程中抛出异常时调用,返回一个HttpResponse对象def process_template_response(self, request, response):
在视图函数执行完毕且试图返回的对象中包含render方法时被调用;该方法需要返回实现了render方法的响应对象
注:中间件中的大多数方法在返回None时表示忽略当前操作进入下一项事件,当返回HttpResponese对象时表示此请求结束,直接返回给客户端
file : middleware/mymiddleware.py
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class MyMiddleWare(MiddlewareMixin):
def process_request(self, request):
print("中间件方法 process_request 被调用")
def process_view(self, request, callback, callback_args, callback_kwargs):
print("中间件方法 process_view 被调用")
def process_response(self, request, response):
print("中间件方法 process_response 被调用")
return response
Copy
注册中间件:
settings.py中需要注册一下 自定义的中间件
file : settings.py
MIDDLEWARE = [
...
]
Copy
注意:配置为数组,中间件被调用时 以 ‘先上到下’ 再 ‘由下到上’的顺序调用
练习1
用中间件实现强制某个IP地址只能向/test开头的地址 发送 5 次请求
提示:
request.META['REMOTE_ADDR']
可以得到远程客户端的IP地址request.path_info
可以得到客户端访问的请求路由信息
中间件执行总流程
某些恶意网站上包含链接、表单按钮或者JavaScript,它们会利用登录过的用户在浏览器中的认证信息试图在你的网站上完成某些操作,这就是跨站请求伪造(CSRF,即Cross-Site Request Forgey)。
CSRF 防范
- django采用 ‘比对暗号’ 机制 防范攻击
- Cookies中存储暗号1, 模板中 表单里藏着 暗号2, 用户只有在本网站下提交数据,暗号2才会随表单提交给服务器,django对比两个暗号,对比成功,则认为是合法请求,否则是违法请求-403响应码
配置步骤
- 分页是指在web页面有大量数据需要显示,为了阅读方便在每个页页中只显示部分数据。
- 好处:
- 方便阅读
- 减少数据提取量,减轻服务器压力。
Django
提供了Paginator
类可以方便的实现分页功能Paginator
类位于django.core.paginator
模块中。
Paginator对象
-
负责分页 数据整体的管理
-
paginator = Paginator(object_list, per_page)
- 参数
object_list
需要分类数据的对象列表per_page
每页数据个数- 返回值:
Paginator
的对象
Paginator属性
count
:需要分类数据的对象总数num_pages
:分页后的页面总数page_range
:从1开始的range对象, 用于记录当前面码数per_page
每页数据的个数
*
page(number)
- 参数 number为页码信息(从1开始)
- 返回当前number页对应的页信息
- 如果提供的页码不存在,抛出
InvalidPage
异常
*
Paginator
异常
exception
–
InvalidPage
:总的异常基类,包含以下两个异常子类
+ PageNotAnInteger
:当向 page()
传入一个不是整数的值时抛出
+ EmptyPage
:当向 page()
提供一个有效值,但是那个页面上没有任何对象时抛出
Page对象
- 负责具体 某一页的数据的管理
Paginator
对象的 page()
方法返回 Page
对象
page = paginator.page(页码)
Copy
object_list
:当前页上所有数据对象的列表number
:当前页的序号,从1
开始-
paginator
:当前page
对象相关的Paginator
对象 -
has_next()
:如果有下一页返回True has_previous()
:如果有上一页返回Truehas_other_pages()
:如果有上一页或下一页返回Truenext_page_number()
:返回下一页的页码,如果下一页不存在,抛出InvalidPage异常previous_page_number()
:返回上一页的页码,如果上一页不存在,抛出InvalidPage异常len()
:返回当前页面对象的个数
逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)
说明:可被常见制表工具 ,如excel等直接进行读取
python 中生成 csv 文件
Python提供了内建库 – csv
; 可直接通过该库操作 csv
文件
案例如下:
import csv
with open('eggs.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['a', 'b', 'c'])
Copy
csv 文件下载
在网站中,实现下载CSV,注意如下:
- 响应
Content-Type
类型需修改为text/csv
。这告诉浏览器该文档是CSV文件,而不是HTML文件 - 响应会获得一个额外的
Content-Disposition
标头,其中包含CSV文件的名称。它将被浏览器用于开启 “另存为…”对话框
import csv
from django.http import HttpResponse
from .models import Book
def make_csv_view(request):
# 响应头
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment;filename="mybook.csv"'
# 查询
all_book = Book.objects.all()
writer = csv.writer(response)
writer.writerow(['id', 'title'])
for b in all_book:
writer.writerrow([b.id, b.title])
return response
Copy
结合分页功能,在 test_page 页面中添加 ‘生成csv’ 的链接;在指定页中点击该链接,生成当前页的csv数据,供用户下载
- 用户可以通过浏览器将图片等文件传到网站
场景:
- 用户上传头像
- 上传流程性的文档[pdf, txt等]
上传规范
- 文件上传必须为
POST
提交方式 - 表单
<form></form>
中文件上传时必须有enctype="multipart/form-data"
伴随时会包含文件内容数据。 - 表单中用
<input type="file" name="xxx">
标签上传文件
文件上传
上传文件
复制
视图功能中,用 request.FILES
取文件框的内容 file=request.FILES['xxx']
说明:
在 setting.py
中设置MEDIA相关配置;Django把用户上传的文件,统统 media
资源
file : settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
复制
在当前项目文件夹下创建 media 文件夹
$ mkdir media
复制
MEDIA_URL和MEDIA_ROOT需要手动绑定
步骤:主语音中添加语音
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
复制
说明:等价于最初 MEDIA_URL
的了解,Django得到该特征请求后去 MEDIA_ROOT
路径寻找资源
file views.py
from django.http import HttpResponse
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
import os
@csrf_exempt
def test_file_upload(request):
"""
文件上传
传统方案: 使用open()
"""
if request.method == 'GET':
return render(request, 'file/test_file_upload.html')
elif request.method == 'POST':
# 文件: file_obj = request.FILES['xx']
# file.file
a_file = request.FILES['myfile']
print('上传文件名是:', a_file.name)
filename = os.path.join(settings.MEDIA_ROOT, a_file.name)
# 写入
with open(filename, 'wb') as f:
data = a_file.file.read()
f.write(data)
return HttpResponse('上传成功!')
复制
- 内容:
FileField(upload='子目录名')
#test_upload/models.py
from django.db import models
Create your models here.
class File(models.Model):
title = models.CharField(max_length=20)
content = models.FileField(verbose_name="文件名称", upload_to="myfiles")
test_upload/views.py
from test_upload.models import *
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
@csrf_exempt
def test_file_upload1(request):
"""
文件上传
方案二: 利用 ORM 进行上传
"""
if request.method == 'GET':
return render(request, 'file/test_file_upload.html')
elif request.method == 'POST':
title = request.POST['title']
file_obj = request.FILES['myfile']
File.objects.create(title=title, content=file_obj)
return HttpResponse('upload file is ok!')
复制
下载规则
Title
点击提交
复制
models.py
from django.db import models
Create your models here.
class File(models.Model):
title = models.CharField(max_length=20)
content = models.FileField(verbose_name="文件名称", upload_to="myfiles")
复制
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.conf import settings
from django.http import StreamingHttpResponse
@csrf_exempt
def download_view(request):
"""
文件下载
"""
if request.method == "GET":
return render(request, 'op/download_file.html')
elif request.method == "POST":
file = File.objects.get(id=1)
file_path = os.path.join(settings.MEDIA_ROOT, str(file.content))
print('--->', file_path)
files = open(file_path, 'rb+')
resp = StreamingHttpResponse(files)
resp['Content-Type]'] = 'application/octet-stream'
filename = file_path.split('/')[-1]
# 下方是解决 浏览器编码问题 下载中文文件乱码
resp['Content-Disposition'] = 'attachment; filename=' + filename.encode('utf-8').decode('ISO-8859-1')
return resp
复制
Django中的用户认证 (使用Django认证系统)
- Django带有一个用户认证系统。它的用户账号、组、权限以及基于cookie的用户会话。
- 用户可以直接使用Django自带的用户表
作用:
基本字段
User
模型类 from django.contrib.auth.models import User
基本模型操作
1. 创建普通用户create_user
from django.contrib.auth.models import User
user = User.objects.create_user(username='用户名', password='密码', email='邮箱',...)
复制
2. 创建超级用户create_superuser
from django.contrib.auth.models import User
user = User.objects.create_superuser(username='用户名', password='密码', email='邮箱',...)
复制
from django.contrib.auth.models import User
try:
user = User.objects.get(username='用户名')
user.is_active = False # 记当前用户无效
user.save()
print("删除普通用户成功!")
except:
print("删除普通用户失败")
复制
from django.contrib.auth import authenticate
user = authenticate(username=username, password=password)
复制
说明:如果用户名密码成功则返回对应的用户对象,否则返回
None
from django.contrib.auth.models import User
try:
user = User.objects.get(username='xiaonao')
user.set_password('654321')
user.save()
return HttpResponse("修改密码成功!")
except:
return HttpResponse("修改密码失败!")
复制
from django.contrib.auth import login
def login_view(request):
user = authenticate(username=username, password=password)
login(request, user)
复制
from django.contrib.auth.decorators import login_required
@login_required
def index_view(request):
"""
该视图必须为用户登录状态下才可访问
当前登陆用户可通过 request.user获取
"""
login_user = request.user
.....
复制
from django.contrib.auth import logout
def logout_view(request):
logout(request)
复制
思考:内建用户表用词怎么办?比如想添加手机号字段?
方案1:通过建立新表,跟内建表做1对1
2:继承内建方案抽象用户模型类
内建用户表 — 继承内建抽象类
注意:此操作要在第一次
Migrate
之前进行
1.
user/models.py
– 添加 user
应用
from django.db import models
from django.contrib.auth.models import AbstractUser
Create your models here.
class UserInfo(AbstractUser):
phone = models.CharField(max_length=11, default='')
复制
2. settings.py添加配置
AUTH_USER_MODEL = 'user.UserInfo'
复制
3. 添加用户
from user.models import UserInfo
UserInfo.objects.create_user(username='guoxiao', password='123456', phone='13488871101')
复制
业务场景
- 业务告警
- 邮件验证
- 密码找回
邮件相关协议
- SMTP的全称是”Simple Mail Transfer Protocol”,即简单邮件传输协议(25号端口)。
- 它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转
-
*属于 “推送” 协议
-
IMAP全称是Internet Mail Access Protocol,即交互式邮件访问协议,是一个应用层协议(端口是143)。
- 用来从本地邮件客户端(Outlook Express、Foxmail、Mozilla Thunderbird等)访问远程服务器上的邮件。
-
*属于 “拉取” 协议
-
POP3是Post Office Protocol 3的简称,即邮局协议的第3个版本,是TCP/IP协议族中的一员(默认端口是110)。
- 本协议主要用于支持使用客户端远程管理在服务器上的电子邮件
- *属于 “拉取” 协议
两者均为 “拉取”型协议,负责从邮件服务器中 下载邮件
- IMAP 具备 摘要浏览功能,可预览部分摘要,再下载整个邮件
- IMAP 为双向协议,客户端操作可反馈给服务器
- POP3 必须下载全部邮件,无摘要功能
- POP3 为单向协议,客户端操作无法同步服务器
Django发邮件
Django中配置邮件功能,主要为SMTP协议,负责发邮件
原理:
- 给Django授权一个邮箱
- Django用该邮箱给对应收件人发送邮件
django.core.mail
封装了 电子邮件的自动发送SMTP
协议
settings.py
设置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qq.com' # 腾讯QQ邮箱 SMTP 服务器地址
EMAIL_PORT = 25 # SMTP服务的端口号
EMAIL_HOST_USER = 'xxxx@qq.com' # 发送邮件的QQ邮箱
EMAIL_HOST_PASSWORD = '******' # 在QQ邮箱->设置->帐户->"POP3/IMAP......服务" 里得到的在第三方登录QQ邮箱授权码
EMAIL_USE_TLS = False # 与SMTP服务器通信时,是否启动TLS链接(安全链接)默认False
Copy
视图函数中
from django.core import mail
mail.send_mail(
subject, #题目
message, # 消息内容
from_email, # 发送者[当前配置邮箱]
recipient_list=['xxx@qq.com'], # 接收者邮件列表
)
Copy
邮箱警告
用中间件实现抓取视图函数的异常,并以邮件的形式将异常信息发送给 指定联系人
- 邮件主题: ‘mysite7异常告警’
- 内容:自定义即可,要求带有 异常信息
-
收件人要求可灵活配置
-
项目部署是指在软件开发完毕后,将开发机器上运行的开发板软件实际安装到服务器上进行长期运行
- 部署要分以下几个步骤进行
- 在安装机器上安装和配置同版本的环境
- django 项目迁移
sudo scp /home/tarena/django/mysite1 root@88.77.66.55:/home/root/xxx
请输入root密码:
Copy
- 用 uwsgi 替代
python3 manage.py runserver
方法启动服务器 - 配置 nginx 反向代理服务器
- 用nginx 配置静态文件路径,解决静态路径问题
uWSGI 网关接口配置 (ubuntu 18.04 配置)
- WSGI (Web Server Gateway Interface)Web服务器网关接口,是Python应用程序或框架和Web服务器之间的一种接口,被广泛使用
- 使用
python manage.py runserver
通常只在开发和测试环境中使用。 -
当开发结束后,完善的项目代码需要在一个高效稳定的环境中运行,这时可以使用WSGI
-
uWSGI是WSGI的一种, 它实现了 http协议 WSGI协议 以及 uwsgi协议
- uWSGI功能完善,支持协议众多,在python web圈热度极高
-
uWSGI 主要以学习配置为主
-
终端输入如下命令
sudo pip3 install uwsgi==2.0.18 -i https://pypi.tuna.tsinghua.edu.cn/simple/
Copy
- 检查是否安装成功
sudo pip3 freeze|grep -i 'uwsgi'
如果成功安装,则会输出
uWSGI==2.0.18
Copy
- 添加配置文件
项目同名文件夹/uwsgi.ini
如:mysite1/mysite1/uwsgi.ini
[uwsgi]
套接字方式的 IP地址:端口号
socket=127.0.0.1:8000
Http通信方式的 IP地址:端口号
http=127.0.0.1:8000
项目当前工作目录
chdir=/home/tarena/.../my_project 这里需要换为项目文件夹的绝对路径
项目中wsgi.py文件的目录,相对于当前工作目录
wsgi-file=my_project/wsgi.py
进程个数
process=4
每个进程的线程个数
threads=2
服务的pid记录文件
pidfile=uwsgi.pid
服务的目志文件位置
daemonize=uwsgi.log
开启主进程管理模式
master=true
Copy
特殊说明:Django 的 settings.py
需要做如下配置
- 启动 uwsgi
$ 进入到项目同名文件夹下 【即settings.py所在目录】
$ uwsgi --ini uwsgi.ini
Copy
- 停止 uwsgi
$ 进入到项目同名文件夹下 【即settings.py所在目录】
$ uwsgi --stop uwsgi.pid
Copy
- 在浏览器端输入
- 注意,此时端口号为8000
- 如果当前有预期返回,则uWSGI启动成功
nginx 及反向代理配置
- Nginx是轻量级的高性能Web服务器,提供了诸如HTTP代理和反向代理、负载均衡、缓存等一系列重要特性,在实践之中使用广泛。
- C语言编写,执行效率高
- nginx 作用
- 负载均衡, 多台服务器轮流处理请求
- 反向代理
- 原理:客户端请求nginx,再由nginx 将请求转发 uWSGI 运行的django
sudo apt install nginx
如果下载速度很慢,考虑更换为国内源
vim /etc/apt/sources.list
更改国内源
sudo apt-get update
Copy
安装完毕后,ubuntu终端中 输入 nginx -v 显示如下:
nginx version: nginx/1.14.0(ubuntu)
Copy
- *
修改nginx 的配置文件 /etc/nginx/sites-enabled/default
在server节点下添加新的location项,指向uwsgi的ip与端口。
server {
...
location / {
uwsgi_pass 127.0.0.1:8000; # 重定向到127.0.0.1的8000端口
include /etc/nginx/uwsgi_params; # 将所有的参数转到uwsgi下
}
...
}
Copy
- nginx服务控制
$ sudo /etc/init.d/nginx start|stop|restart|status
或
$ sudo service nginx start|stop|restart|status
Copy
通过
start,stop,restart,status
可能实现nginx服务的启动、停止、重启、状态
修改uWSGI配置
- 说明
nginx
负责接收请求,并把请求转发给后面的uWSGI
- *修改
项目同名文件夹/uwsgi.ini
下的Http通信方式改为socket通信方式
[uwsgi]
去掉如下
http=127.0.0.1:8000
改为
socket=127.0.0.1:8000
Copy
- *重启uWSGI服务
进入到 项目同名文件夹下
$ uwsgi --stop uwsgi.pid
$ uwsgi --ini uwsgi.ini
Copy
- 测试:
- 在浏览器端输入
- 注意 : 1,此时端口号为80(nginx默认值) 2,Django中有任何修改 需要重启 uwsgi , 否则修改不生效
nginx+uwsgi排错
排查问题宗旨 -> 看日志! 看日志!! 看日志!!!
- 异常信息
/var/log/nginx/error.log
- 正常访问信息
/var/log/nginx/access.log
项目同名目录下, uwsgi.log
nginx 配置静态文件路径
admin样式丢失 – 静态文件加载失败
解决方案:静态文件交由 nginx 统一处理,让nginx加载静态文件
file : /etc/nginx/sites-enabled/default
新添加location /static 路由配置,重定向到指定的 第一步创建的路径即可
server {
...
location /static {
# root 第一步创建文件夹的绝对路径,如:
root /home/tarena/项目名_static;
}
...
}
img src='/static/a.jpg'
Copy
重启 nginx - sudo /etc/init.d/nginx restart
404/500 界面 定义和配置
- 在模板文件夹内添加 404.html 模版,当视图触发
Http404
异常时将会被显示 - 404.html 仅在发布版中(即
setting.py
中的DEBUG=False
时) 才起作用 - 当向应处理函数触发
Http404
异常时就会跳转到404界面
from django.http import Http404
def xxx_view( ):
raise Http404 # 直接返回404
Copy
邮件告警
- 当正式服务器上代码运行有报错时,可将错误追溯信息发至指定的邮箱
- 配置如下
settings.py
中
在基础邮件配置之后 添加如下
关闭调试模式
DEBUG = False
错误报告接收方
ADMINS = [('guoxiaonao', 'xxxx@example.com'), ('wanglaoshi', 'xxxx@example.com')]
发送错误报告方,默认为 root@localhost账户,多数邮件服务器会拒绝
SERVER_EMAIL = 'email配置中的邮箱'
Copy
报错邮件中会显示一些错误的追踪,这些错误追踪中会出现如 password等敏感信息,Django已经将配置文件中的敏感信息 过滤修改为 多个星号,但是用户自定义的视图函数需要用户手动过滤敏感信息
1. 视图函数中的局部变量
from django.views.decorators.debug import sensitive_variables
@sensitive_variables('user', 'pw', 'cc')
def process_info(user):
pw = user.pass_word
cc = user.credit_card_number
name = user.name
...
Copy
注意:
- 若报错邮件中牵扯到user,pw,cc等局部变量的值,则会将其替换成
****
, 而 name 变量还显示其真实值 - 多个装饰器时,需要将其放在最顶部
- 若不传参数,则过滤所有局部变量的值
2. POST提交中的数据
from django.views.decorators.debug import sensitive_post_parameters
@sensitive_post_parameters('password', 'username')
def index(request):
s = request.POST['username'] + request.POST['abcd']
#'abcd' 并不存在,此时引发error
#POST中 username 及 password的值会被替换成 ******
Copy
Original: https://www.cnblogs.com/zouzhibin/p/16329627.html
Author: 我不知道取什么名字好
Title: django2
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/563927/
转载文章受原作者版权保护。转载请注明原作者出处!