Django(十七):静态文件、中间件
一、静态文件
参考:https://www.cnblogs.com/jiajiaba/p/10584329.html
参考:https://docs.djangoproject.com/zh-hans/3.0/ref/settings/#static-files
1.1 使用
在 网页使用的css文件,js文件和图片叫做静态文件。
1)新建静态文件夹 根目录/static/js、css、images
2) 配置静态文件所在的物理目录。
Settings.py
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
# 【1】设置访问静态文件对应的url地址
STATIC_URL = '/static/'
# STATIC_URL = '/abc/'
# 【2】设置静态文件存放的物理目录(django2.0以后似乎无用)
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
说明:
- STATIC_URL 设置访问静态文件对应的url。
 - STATICFILES_DIRS 设置静态文件所在的物理目录。
 
1.2 加载目录过程(了解)
STATICFILES_FINDERS=('django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder')
1.3 模板中动态生成静态文件路径
{% load static %}django2.0以前可能是{% load staticfiles %}<img src="{% static 'images/mm.jpg' %}">
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- 【1】加载静态 -->
    {% load static %}
    <title>首页</title>
</head>
<body>
<h1>首页{{name}}</h1>
<img src="/static/images/mm.jpg"><br/>
<img src="/abc/images/mm.jpg"><br/>
【2】动态获取STATIC_URL,拼接静态文件路径:<br/>
<img src="{% static 'images/mm.jpg' %}">
</body>
</html>
效果:
- 1.1 2) 步的配置文件改变成
STATIC_URL = '/abc/'动态的路径依旧可以得到正确地址。
settings.py 
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
# 【1】设置访问静态文件对应的url地址
# STATIC_URL = '/static/'
STATIC_URL = '/abc/'
# 【2】设置静态文件存放的物理目录(django2.0以后似乎无用)
#STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

二、中间件(函数)
【参考】https://docs.djangoproject.com/zh-hans/3.0/topics/http/middleware/
【中间件函数】是django框架给我们预留的函数接口,让我们可以干预请求和应答的过程。

2.0 实例支持:获取浏览器端的ip地址
使用request对象的META属性:request.META['REMOTE_ADDR']
2.1中间件作用——实例说明
- 目标:过滤指定IP,让它访问不了网站
 
2.2常规解决方法——【装饰器过滤IP】
1)app2/views.py编辑装饰器
EXCLUDE_IPS = ['192.168.1.123','172.16.179.152'] #第1个ip即要禁用的目标主机IP
'''装饰器函数:如果IP在exclude_ids里则返回forbidden'''
def blocked_ips(view_func):
    def wrapper(request, *view_args, **view_kwargs):
        # 获取浏览器端的ip地址
        user_ip = request.META['REMOTE_ADDR']
        if user_ip in EXCLUDE_IPS:
            return HttpResponse('<h1>Forbidden</h1>')
        else:
            return view_func(request, *view_args, **view_kwargs)
    return wrapper
# /index
@blocked_ips #引用装饰器,此页面会禁用指定ip访问
def index (request):
    return render(request,'app2/index.html',{'name':'Tom'})
# /url_reverse
@blocked_ips #引用装饰器,此页面会禁用指定ip访问
def url_reverse (request):
    return render(request,'app2/url_reverse.html')
2)urls配置略过#
3)启动服务
py manage.py runserver 192.168.1.4:8000
4)在局域网的另一台主机(192.168.1.123电脑)访问 192.168.1.4:8000/index 或 url_reverse
显示:Forbidden
5)装饰器方法缺点:虽然也能禁用指定IP,但每个视频函数页面都要调用装饰器@blocked_ips,太过麻烦。
2.3 中间件过滤IP【重点】
【参考】https://segmentfault.com/a/1190000019784702
1)app2/middleware.py 编写中间件
建立文件,自定义中间件函数,详细代码:
- 新建app2/middleware.py文件。
 - 定义中间件类,写中间件函数
 
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
#【1】类继承自MiddlewareMixin,类名可随意写,建议加上Middleware
#django2.0之前写法:class BlockedIPSMiddleware(object)
class BlockedIPSMiddleware(MiddlewareMixin):
    '''中间件类'''
    EXCLUDE_IPS = ['192.168.1.123','172.16.179.152']
    #【2】此处是process_view函数重写,因此写法固定,不能变(包括函数名、参数)
    def process_view(self, request, view_func, *view_args, **view_kwargs):
        '''视图函数调用之前会调用'''
        user_ip = request.META['REMOTE_ADDR']
        if user_ip in BlockedIPSMiddleware.EXCLUDE_IPS:
            return HttpResponse('<h1>Forbidden</h1>')
2)【project2/settings.py】配置中间件
【1】注册过滤IP的中间件类名(app2文件夹下.middleware.py文件下.BlockedIPSMiddleware类)
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware', #django默认打开csrf防护,它只对post提交有效
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'app2.middleware.BlockedIPSMiddleware' # 【1】注册过滤IP的中间件类名(app2文件夹下.middleware.py文件下.BlockedIPSMiddleware类)
]
附)app2/views.py
from django.shortcuts import render,redirect
from django.template import loader,RequestContext
from django.http import HttpResponse,JsonResponse
from app2.models import BookInfo
EXCLUDE_IPS = ['192.168.1.123','172.16.179.152']
'''装饰器函数:如果IP在exclude_ids里则返回forbidden'''
def blocked_ips(view_func):
    def wrapper(request, *view_args, **view_kwargs):
        # 获取浏览器端的ip地址
        user_ip = request.META['REMOTE_ADDR']
        if user_ip in EXCLUDE_IPS:
            return HttpResponse('<h1>Forbidden</h1>')
        else:
            return view_func(request, *view_args, **view_kwargs)
    return wrapper
# /index
#@blocked_ips
def index (request):
    return render(request,'app2/index.html',{'name':'Tom'})
# /url_reverse
#@blocked_ips
def url_reverse (request):
    return render(request,'app2/url_reverse.html')
# /temp_tags
def temp_tags(request):
    '''模板标签'''
    # 1. 查找所有图书的信息
    books = BookInfo.objects.all()
    return render(request,'app2/temp_tags.html', {'books':books})
3)效果:再启动服务器:
1.打开cmd运行
py manage.py runserver 192.168.1.4:8000
2.另一台电脑(192.168.1.123)访问任意网址:http://192.168.1.4:8000/temp_tags/
http://192.168.1.4:8000/index/等等。都会自动提示:
Forbidden
3. 这样就不必加装饰器函数、逐个@装饰器函数了
2.4 django2.0之后MiddlewareMixin中间件类的其它函数及作用

1)process_request:
这是请求来到 middleware 中时讲入的第一个方法。一般情优下,我们以在这里做一些校验,比如
户登录或者 HTTP 中是否有认证头之类的验证.这个方法可以有两种返回值 HttpResnonse 或者None,如果返回 HttpResponse,那么接下米的处理方法只会执行 process_response,其他方法将不会被执行。这里需要注意的是,如果你的 middleware 是 settings 配置的 MIDDLEWARE 的第一个,那么剩下的 middleware 也不会被执行;如果返回 None,那么 Diango会继续执行其他方法。
2)process_view:
这个方法是在 process_request 方法之后执行的,参数如上面代码所示,其中 func 就是我们将要执行的 view 方法。因此,如果要统计一个view的执行时间,可以在这里做。它的返回值跟 process_request 一样,是HttpResponse 或者 None,其逻辑也一样。如果返回 None,那么 Django 会帮你执行 view 函数,从而得到最终的 response。
3)Process_template_response:
执行完上面的方法,并且 Django 帮我们执行完 view,拿到最终的 response 后,如果使用了模板的 response (这是指通过 return render(request,'index.html',context={})方式返回的 response),就会来到这个方法中。 在这个方法中,我们可以对 response 做一下操作,比如 Content-Type 设置,或者其他 header 的修改/增加。
4)process_response:
当所有流程都处理完毕后,就来到了这个方法。这个方法的逻辑跟 process_template_response是完全一样的,只是后者是针对带有模板的response的处理。
5)process_exception:
上面的处理方法是按顺序介绍的,而这个方法不太一样。只有在发生异常时,才会进入这个方法。哪个阶段发生的异常呢?
可以简单理解为在将要调用的 View 中出现异常(就是在process_view 的 func 函数中)或者返回的模板 response 在渲染时发生的异常。但是需要注意的是,如果你在process_view 中手动调用了 func,就像我们上面做的那样,就不会触发 process_exception 了。这个方法接收到异常之
后,可以选择处理异常,然后返回一个含有异常信息的 HttpResponse,或者直接返回 None 不处理,这种情况下 Django会使用自己的异常模板。
2.5)django2.0之前middleware函数:
在类中定义中间件预留函数。
__init__:服务器响应第一个请求的时候调用。
process_request:是在产生request对象,进行url匹配之前调用。
process_view:是url匹配之后,调用视图函数之前。
process_response:视图函数调用之后,内容返回给浏览器之前。
process_exception:视图函数出现异常,会调用这个函数。
如果注册的多个中间件类中包含process_exception函数的时候,调用的顺序跟注册的顺序是相反的。
2.6)中间件各函数调用过程实例演示
1)app2/middleware.py 编写中间件
django2.0后写法
class TestMiddleware(MiddlewareMixin):
    '''中间件类'''
    def __init__(self,get_response):#【1】重点一此处必须多加参数,get_response,否则报错: __init__() takes 1 positional argument but 2 were given
        '''服务器重启之后,接收第一个请求时调用'''
        #super().__init__()
        self.get_response = get_response #【2】此处必须得到父类的get_response属性,否则报错 __init__() takes 1 positional argument but 2 were given
        print('----init----')
    def process_request(self, request):
        '''产生request对象之后,url匹配之前调用'''
        print('----process_request----')
        # return HttpResponse('process_request')
    def process_view(self, request, view_func, *view_args, **view_kwargs):
        '''url匹配之后,视图函数调用之前调用'''
        print('----process_view----')
        return HttpResponse('process_view')
    def process_response(self, request, response):
        '''视图函数调用之后,内容返回浏览器之前'''
        print('----process_response----')
        return response
django2.0之前写法
'''django2.0之前写法'''
from django.http import HttpResponse
class TestMiddleware(object):
    '''中间件类'''
    def __init__(self):
        '''服务器重启之后,接收第一个请求时调用'''
        print('----init----')
    def process_request(self, request):
        '''产生request对象之后,url匹配之前调用'''
        print('----process_request----')
        # return HttpResponse('process_request')
    def process_view(self, request, view_func, *view_args, **view_kwargs):
        '''url匹配之后,视图函数调用之前调用'''
        print('----process_view----')
        return HttpResponse('process_view')
    def process_response(self, request, response):
        '''视图函数调用之后,内容返回浏览器之前'''
        print('----process_response----')
        return response
2)app2/views.py
from django.shortcuts import render
# /index
#@blocked_ips
def index (request):
	'''首页'''
    print('----index----')
    return render(request,'app2/index.html',{'name':'Tom'})
3)配置settings.py
【1】注册中间件流程测试类名
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware', #django默认打开csrf防护,它只对post提交有效
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'app2.middleware.BlockedIPSMiddleware', # 注册过滤IP的类名
    'app2.middleware.TestMiddleware', #【1】注册中间件流程测试类名
]
效果:http://127.0.0.1:8000/index/
process_view
1. 正常运行(把首页截断不运行)
控制台输出(即可看到中间件各函数运行流程):
- 第一次会执行init
 - 再次请求就不再调用它了
 
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
----init----
----process_request----
----process_view----
----process_response----
[14/Jan/2020 10:58:16] "GET /index/ HTTP/1.1" 200 12
----process_request----
----process_view----
----process_response----
[14/Jan/2020 11:01:39] "GET /index/ HTTP/1.1" 200 12
2. 如果把process_request解除注释(后面步骤截断)
可以看到后面都被截断不再运行了。
def process_request(self, request):
        '''产生request对象之后,url匹配之前调用'''
        print('----process_request----')
        return HttpResponse('process_request')
控制台输出
----process_request----
----process_response----
[14/Jan/2020 11:22:36] "GET /index/ HTTP/1.1" 200 15
3. 如果这两个函数都注释掉:
def process_request(self, request):
        '''产生request对象之后,url匹配之前调用'''
        print('----process_request----')
        # return HttpResponse('process_request')
    def process_view(self, request, view_func, *view_args, **view_kwargs):
        '''url匹配之后,视图函数调用之前调用'''
        print('----process_view----')
        #return HttpResponse('process_view')
则控制台输出:
- 可以看到首页被加载了
 
Quit the server with CTRL-BREAK.
----init----
----process_request----
----process_view----
----index----
----process_response----
[14/Jan/2020 11:25:45] "GET /index/ HTTP/1.1" 200 349
----process_request----
----process_response----
Not Found: /static/images/mm.jpg
[14/Jan/2020 11:25:45] "GET /static/images/mm.jpg HTTP/1.1" 404 4316
[14/Jan/2020 11:25:45] "GET /abc/images/mm.jpg HTTP/1.1" 404 1659
2.6)发生异常的中间件
1)app2/middleware.py 编写异常处理中间件
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class ExceptionTest1Middleware(MiddlewareMixin):
    def process_exception(self, request, exception):
        '''视图函数发生异常时调用'''
        print('----process_exception1----')
        print(exception)
class ExceptionTest2Middleware(MiddlewareMixin):
    def process_exception(self, request, exception):
        '''视图函数发生异常时调用'''
        print('----process_exception2----')
2)注册中间件settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware', #django默认打开csrf防护,它只对post提交有效
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    #'app2.middleware.BlockedIPSMiddleware', # 注册过滤IP的类名
    #'app2.middleware.TestMiddleware', #注册中间件流程测试类名
    'app2.middleware.ExceptionTest1Middleware', #【1】异常处理中间件
    'app2.middleware.ExceptionTest2Middleware', #【2】异常处理中间件,它们的调用顺序是自下往上的
]
3)写一个错误到视图函数app2/views.py
# /index
#@blocked_ips
def index (request):
    '''首页'''
    name='a'+2 #【错误】用字符串和数字相加
    print('----index----')
    return render(request,'app2/index.html',{'name':'Tom'})
效果:http://127.0.0.1:8000/index/
报错:
TypeError at /index/
can only concatenate str (not "int") to str
控制台输出:
【1-2】处
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
----process_exception2---- 【1】
----process_exception1----【2】
can only concatenate str (not "int") to str
Internal Server Error: /index/
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-p
ackages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-p
ackages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-p
ackages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "D:\a\django-app\project2\app2\views.py", line 155, in index
    name='a'+2
TypeError: can only concatenate str (not "int") to str
[14/Jan/2020 11:54:35] "GET /index/ HTTP/1.1" 500 69194
												
											Django(十七):静态文件、中间件的更多相关文章
- Django之静态文件,中间件,admin后台管理
		
静态文件 静态文件的使用 在 网页使用的css文件,js文件和图片等叫做静态文件.1)在项目下新建静态文件夹 static. 2) 配置静态文件所在的物理目录.Settings.py STATIC_U ...
 - [Django框架 - 静态文件配置、request对象方法初识、 pycharm链接数据库、ORM实操增删改查、django请求生命周期]
		
[Django框架 - 静态文件配置.request对象方法初识. pycharm链接数据库.ORM实操增删改查.django请求生命周期] 我们将html文件默认都放在templates文件夹下 将 ...
 - [django]windows下用Django,静态文件请求失败,出现UnicodeDecodeError
		
问题:windows下用Django,静态文件请求失败,出现UnicodeDecodeError:'utf-8' codec can't decode byte 0xb0 in position 1: ...
 - django处理静态文件
		
静态文件指的是js css 还有图片这些,配置方法如下 1. 在设置文件(settings.py)中,installed_apps中添加 django.contrib.staticfiles 然后设置 ...
 - Django中静态文件引用优化
		
静态文件引用优化 在html文件中是用django的静态文件路径时,一般会这么写: <script type="text/javascript" src="/sta ...
 - django的静态文件的引入
		
django的静态文件的引入 1.路径配置 在templates文件夹的同级目录下新建static文件夹 在setting里面写上STATICFILES_DIRS = [os.path.join(BA ...
 - apache上部署django的静态文件
		
一直在优化自己博客的代码, 昨天把css样式表分离出来, 用作静态 文件, 但是自己还没学django怎么使用静态文件, 经过一番google 终于解决了. django 使用静态文件有两种方法, 一 ...
 - django配置静态文件
		
django配置静态文件 参考文章链接:http://blog.csdn.net/hireboy/article/details/8806098
 - django 设置静态文件,static
		
django 设置静态文件,static 一.搜集静态文件 1.1 命令行查看 collectstatic guoguos-MacBook-Pro:mysite guoguo$ python mana ...
 - gunicorn启动django时静态文件的加载
		
目前在用nginx+gunicorn对django进行部署 当我用gunicorn -w 4 -b 127.0.0.1:8080 myproject.wsig:application启动django时 ...
 
随机推荐
- 3000 - No Mycat Database selected
			
今天在linux上搭建好mycat后,用Navicat连接出现如下错误 尝试很多方式发现并没有什么用,后面改用SQLyog连接就可以正常使用了!!!
 - Linux--如何通过图形界面选项快速更改ubuntu的窗口、图标、分辨率大小,超详细超实用~(适合所有人群)
			
这是默认ubuntu给出的分辨率大小:800*600,说实话有点小不适合操作. (分辨率800*600) 这是调整后的分辨率大小. (分辨率1400*900) 操作方法: 首先点击选项框中的设置图标- ...
 - 《JavaScript高级程序设计》读书笔记(三)基本概念第一小节
			
内容---语法 本小节---数据类型 本小节 undefined,null,Boolean---流程控制语句---理解函数 任何语言的核心都必然会描述这门语言最基本的工作原理.而描述的内容通常都要涉及 ...
 - JavaScript - onunload失效
			
参考 https://stackoverflow.com/questions/7794301/window-onunload-is-not-working-properly-in-chrome-bro ...
 - C、C++ 不得宠,微软正开发新的编程语言!
			
76 年迭代与更新,编程语言界,谁主沉浮? 在六百多种编程语言中,对于开发者而言,其主观印象中或只有几种主流的编程语言,如 Java.C.C++.C#.新贵 Python 等,而之所以它们能够成为主流 ...
 - ISBN号码(0)<P2008_1>
			
ISBN号码 (isbn.pas/c/cpp) [问题描述] 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如“x-xxx-xxxx ...
 - 树莓派4B踩坑指南 - (5)设置阿里云的源及解决apt提示依赖
			
解决树莓派apt升级/安装提示依赖问题: 注意!!buster是根据系统版本(cat /etc/os-release)来写的,如果是jessie或者stretch要改为buster.参考解决树莓派ap ...
 - java 调用阿里云短信接口,报InvalidTimeStamp.Expired : Specified time stamp or date value is expired.
			
官网解释: 问题所在: 自己的电脑(或者服务器) 的时间与阿里云的服务器时间 相差15分钟了. 解决方法 : 把自己的电脑时间 (或者服务器)的时间 改成标准的北京时间就行了.
 - Python  基础之面向对象初识与类的封装
			
一.面向对象类的初识 1.类的定义 #三种方式:#1.class MyClass: pass #2.推荐class MyClass(): pass #3.class MyClass(obj ...
 - .Net使用SharpZip解压缩文件
			
最近,项目中使用到了上传压缩文件,文件上传到服务器后,肯定要解压,取出其中的文件才能使用,在这里做一个小结,Get这个新技能. 首先在使用NuGet管理程序在项目中添加引用ICSharpCode.Sh ...