怎么建立一个属于自己的网站,dw做的网站 图片的路径,百度做网站电话多少,做地方行业门户网站需要什么资格缓存
缓存是一类可以更快的读取数据的介质统称#xff0c;读取硬盘、较复杂的计算、渲染都会产生较大的耗时。数据变化频率不会很高的场景适合使用缓存。使用缓存场景#xff1a;博客列表页、电商商品详情页、缓存导航及页脚。
Django中设置缓存
Django中提供多种缓存方式…缓存
缓存是一类可以更快的读取数据的介质统称读取硬盘、较复杂的计算、渲染都会产生较大的耗时。数据变化频率不会很高的场景适合使用缓存。使用缓存场景博客列表页、电商商品详情页、缓存导航及页脚。
Django中设置缓存
Django中提供多种缓存方式如需使用需要在settings.py中进行配置
初始化配置
[rootvm ~]# mysql -uroot -p123456 -e create database mysite7 default charset utf8;[rootvm ~]# django-admin startproject mysite7
[rootvm ~]# cd mysite7/
[rootvm mysite7]# vim mysite7/settings.pyALLOWED_HOSTS [*,]DATABASES {default : {ENGINE: django.db.backends.mysql,NAME: mysite7,USER: root,PASSWORD: 123456,HOST: 127.0.0.1,PORT: 3306,}
}
LANGUAGE_CODE zh-HansTIME_ZONE Asia/Shanghai[rootvm mysite7]# python3 manage.py runserver 0.0.0.0:8000
[rootvm mysite7]# python3 manage.py migrate
[rootvm mysite7]# mysql -uroot -p123456 -e use mysite7;show tables;1、数据库缓存
mysite7 改配置 migrate , 添加缓存配置项 createcachetable
Django可以将其缓存的数据存储在您的数据库中
[rootvm mysite7]# vim mysite7/settings.py
#添加到最后
CACHES {default: {BACKEND: django.core.cache.backends.db.DatabaseCache,LOCATION: my_cache_table,TIMEOUT: 300, #缓存保存时间 单位秒默认值为300, OPTIONS:{MAX_ENTRIES: 300, #缓存最大数据条数CULL_FREQUENCY: 2,#缓存条数达到最大值时 删除1/2的缓存数据}}
}创建缓存表
[rootvm mysite7]# python3 manage.py createcachetable
[rootvm mysite7]# mysql -uroot -p123456 -e desc mysite7.my_cache_table;
----------------------------------------------------
| Field | Type | Null | Key | Default | Extra |
----------------------------------------------------
| cache_key | varchar(255) | NO | PRI | NULL | |
| value | longtext | NO | | NULL | |
| expires | datetime(6) | NO | MUL | NULL | |
----------------------------------------------------2、文件系统缓存
CACHES {default: {BACKEND: django.core.cache.backends.filebased.FileBasedCache,LOCATION: /var/tmp/django_cache,#这个是文件夹的路径#LOCATION: c:\test\cache,#windows下示例}
}3、本地内存缓存
CACHES {default: {BACKEND: django.core.cache.backends.locmem.LocMemCache,LOCATION: unique-snowflake}
}Django中使用缓存
在urls中使用(较少)
from django.views.decorators.cache import cache_pageurlpatterns [path(foo/, cache_page(60)(my_view) ),
]在模板中使用(较少)
{% load cache %} {% cache 500 sidebar username %}.. sidebar for logged in user ..
{% endcache %}在Views中使用
from django.views.decorators.cache import cache_pagecache_page(30) - 单位s
def my_view(request):...使用举例
[rootvm mysite7]# vim mysite7/urls.py
from . import views
urlpatterns [path(test_cache/,views.test_cache),
...[rootvm mysite7]# vim mysite7/views.py
from django.http import HttpResponse
import timedef test_cache(request):t time.time()# 经历了复杂计算或复杂查询time.sleep(10)return HttpResponse(time is %s % t)http://192.168.1.11:8000/test_cache/ #访问很慢network栏看到用时10s缓存装饰器
不灵活不方便修改清理
[rootvm mysite7]# vim mysite7/views.py
from django.http import HttpResponse
import time
from django.views.decorators.cache import cache_pagecache_page(600)
def test_cache(request):...http://192.168.1.11:8000/test_cache/ #第一次很慢后面很快但是时间没变化
[rootvm net_note]# mysql -uroot -p123456 -e select * from mysite7.my_cache_table\G缓存api
作用局部缓存部分结果
set、get、delete、add 、get_or_set、set_many、get_many、delete_many
#指定配置引入,多个缓存import caches
from django.core.cache import caches
cache1 caches[myalias]
cache2 caches[myalias_2]#默认配置引入【指的配置中的default项】 等同于 caches[default]
from django.core.cache import cache#常规命令 set
#key: 字符串类型
#value: Python对象
#timeout缓存存储时间 默认值为settings.py CACHES对应配置的TIMEOUT
#返回值None
cache.set(my_key, myvalue, 30)#常规命令 get
#返回值为key的具体值如果没有数据则返回None
cache.get(my_key)
#可添加默认值如果没取到返回默认值
cache.get(my_key, default值)#常规命令 delete
#返回值 None
cache.delete(my_key)#常规命令 add 只有在key不存在的时候 才能设置成功
#返回值 True or False
cache.add(my_key, value) #如果my_key已经存在则此次赋值失效#常规命令 get_or_set 如果未获取到数据 则执行set操作
#返回值 key的值
cache.get_or_set(my_key, value, 10)#常规命令 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}#常规命令 delete_many
#返回值 成功删除的数据条数
cache.delete_many([a, b, c])[rootvm mysite7]# python3 manage.py shellfrom django.core.cache import cachecahe.set(user,django,600)cache.get(user)
djangocache.delete(user)cache.get(user) cache.add(user,django,600)
Truecache.add(user,django,600)
Falsecache.get(user)
django cache.get_or_set(user2,django,600)
djangocache.get_or_set(user2,dj,600)
django浏览器中的缓存
强缓存
不会向服务器发送请求直接从缓存中读取资源
Expires
缓存过期时间用来指定资源到期的时间是服务器端的具体的时间点
Expires: Thu, 02 Apr 2030 05:14:08 GMT
Expires是 HTTP/1 的产物受限于本地时间如果修改了本地时间可能会造成缓存失效Cache-Control
在HTTP/1.1中Cache-Control主要用于控制网页缓存。
比如当Cache-Control:max-age120 代表请求创建时间后的120秒缓存失效一般情况下两个值都会设置浏览器查看Response Header里的Expires、Cache-Control
协商缓存
协商缓存就是强制缓存失效后浏览器携带缓存标识向服务器发起请求由服务器根据缓存标识决定是否使用缓存的过程
Last-Modified和If-Modified-Since
第一次访问时服务器会返回文件的最近修改时间 Last-Modified:
浏览器下次请求时 携带If-Modified-Since这个header , 该值为 Last-Modified
服务器接收请求后对比结果若资源未发生改变则返回304否则返回200并将新资源返回给浏览器缺点只能精确到秒容易发生单秒内多次修改检测不到
ETag和If-None-Match
Etag是服务器响应请求时返回当前资源文件的一个唯一标识(由服务器生成)只要资源有变化Etag就会重新生成。流程同上判断是否match。
对比Last-ModifiedEtag精度高、Etag优先级高、性能不如Last-Modifi
中间件 Middleware
中间件是 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对象时表示此请求结束直接返回给客户端
编写中间件类:
[rootvm mysite7]# mkdir middleware
[rootvm mysite7]# vim middleware/mymiddleware.pyfrom django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixinclass 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注册中间件:
[rootvm mysite7]# vim mysite7/settings.py
...
MIDDLEWARE [...middleware.mymiddleware.MyMiddleWare,]使用测试验证
[rootvm mysite7]# vim mysite7/urls.py
urlpatterns [
...path(test_mw, views.test_mw),path(test_mw2, views.test_mw2),[rootvm mysite7]# vim mysite7/views.py
...
def test_mw(request):print(---view in test_mw---)return HttpResponse(test mw is OK!)def test_mw2(request):print(---view in test_mw2---)return HttpResponse(test mw2 is OK!) 访问http://192.168.1.11:8000/test_mw test mw is OK!
终端日志中间件方法 process_request 被调用中间件方法 process_view 被调用---view in test_mw---中间件方法 process_response 被调用
访问http://192.168.1.11:8000/test_mw2 也会有日志显示影响全局 中间件执行的顺序
重新复制一套MyMiddleWare2 访问执行顺序如下进和出方向正好相反(洋葱图了解)
访问http://192.168.1.11:8000/test_mw 中间件方法 process_request 被调用中间件方法2 process_request 被调用中间件方法 process_view 被调用中间件方法2 process_view 被调用---view in test_mw---中间件方法2 process_response 被调用中间件方法 process_response 被调用练习
用中间件实现强制某个IP地址只能向/test 发送 5 次GET请求提示:- request.META[REMOTE_ADDR] 可以得到远程客户端的IP地址- request.path_info 可以得到客户端访问的GET请求路由信息- 在进url之前统计次数做出处理[rootvm mysite7]# vim middleware/mymiddleware.py
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
import reclass MyMW(MiddlewareMixin):# 统计每一个客户端IP以及对应的访问次数visit_times {}def process_request(self, request):# 1. 只对/test开头的路由做5次访问的限制if not re.match(r^/test, request.path_info):return# 2. 获取客户端的IP地址cip request.META[REMOTE_ADDR]# 3. 获取访问次数,回去cip的次数默认是0次times self.visit_times.get(cip, 0)# 4. 判断是否超过5次if times 5:return HttpResponse(no way!)# 5.每访问一次次数1self.visit_times[cip] times 1print(%s visit we %s times % (cip,self.visit_times[cip]))[rootvm mysite7]# vim mysite7/settings.pymiddleware.mymiddleware.MyMW, 访问测试看日志输出 192.168.1.1 visit we 1 times 5次后看浏览器返回no way
跨站请求伪造攻击 CSRF
跨站请求伪造攻击
某些恶意网站上包含链接、表单按钮或者JavaScript它们会利用登录过的用户在浏览器中的认证信息(cookie)试图在你的网站上完成某些操作这就是跨站请求伪造(CSRF即Cross-Site Request Forgey)。
说明: CSRF中间件和模板标签提供对跨站请求伪造简单易用的防护。
作用: 不让其它表单提交到此 Django 服务器
防范步骤
打开MIDDLEWARE
打开MIDDLEWARE中django.middleware.csrf.CsrfViewMiddleware默认打开
添加csrf_token
模板中form标签下添加如下标签 form action....{% csrf_token %}.../form关闭个别试图csrf
如果某个视图不需要django进行csrf保护可以用装饰器关闭对此视图的检查
from django.views.decorators.csrf import csrf_exemptcsrf_exempt
def my_view(request):return HttpResponse(Hello world)使用测试
[rootvm mysite7]# vim mysite7/urls.pypath(test_csrf, views.test_csrf),[rootvm mysite7]# vim mysite7/views.py
from django.http import HttpResponse
from django.shortcuts import renderdef test_csrf(request):if request.method GET:return render(request, test_csrf.html)elif request.method POST:name request.POST[name]return HttpResponse(欢迎您,%s % name)[rootvm mysite7]# vim mysite7/settings.py
TEMPLATES [{BACKEND: django.template.backends.django.DjangoTemplates,DIRS: [os.path.join(BASE_DIR,templates)],[rootvm mysite7]# mkdir -p templates
[rootvm mysite7]# vim templates/test_csrf.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleCSRF/title
/head
bodyform action/test_csrf methodpostp名称:input typetext namename/pinput typesubmit value提交/form
/body
/html#访问 http://192.168.1.11:8000/test_csrf 输入名称提交
# 报CSRF验证失败. 请求被中断. 看下面的help里的 {% csrf_token %} template tag
#写到form表单里form action/test_csrf methodpost{% csrf_token %}p名称:input typetext namename/pinput typesubmit value提交/form#再次访问查看网页源代码,多出一个csrf的token
input typehidden namecsrfmiddlewaretoken valueoqLeUQSpIy...点击提交按钮,中间件的方法先于视图函数被调用在中间方法中验证先前给你的csrfmiddlewaretoken验证存在并正确放行调用视图函数完成相应的功能。web分页功能
分页是指在web页面有大量数据需要显示为了阅读方便在每个页页中只显示部分数据。
好处: 方便阅读减少数据提取量减轻服务器压力。
Django通过使用Paginator和Page这两个类来完成的分页
Paginator对象
负责分页数据整体的管理位于django.core.paginator 模块中。
对象的构造方法paginator Paginator(object_list, per_page)
参数object_list 需要分类数据的对象列表per_page 每页数据个数
返回值: Paginator的对象Paginator属性- count需要分类数据的对象总数- num_pages分页后的页面总数- page_range从1开始的range对象, 用于记录当前面码数- per_page 每页数据的个数Paginator方法- page(number)- 参数 number为页码信息(从1开始)- 返回当前number页对应的页信息- 如果提供的页码不存在抛出InvalidPage异常Paginator异常exception- InvalidPage总的异常基类包含以下两个异常子类- PageNotAnInteger当向page()传入一个不是整数的值时抛出- EmptyPage当向page()提供一个有效值但是那个页面上没有任何对象时抛出Page对象
负责具体某一页的数据的管理Paginator对象的page()方法返回Page对象
创建对象 page paginator.page(页码)Page对象属性- object_list当前页上所有数据对象的列表- number当前页的序号从1开始- paginator当前page对象相关的Paginator对象Page对象方法- has_next()如果有下一页返回True- has_previous()如果有上一页返回True- has_other_pages()如果有上一页或下一页返回True- next_page_number()返回下一页的页码如果下一页不存在抛出InvalidPage异常- previous_page_number()返回上一页的页码如果上一页不存在抛出InvalidPage异常- len()返回当前页面对象的个数说明: Page 对象是可迭代对象,可以用 for 语句来 访问当前页面中的每个对象
参考文档 https://docs.djangoproject.com/en/2.2/topics/pagination/分页示例:
视图函数
from django.core.paginator import Paginator
def book(request): # 1. 准备要分页的数据bks Book.objects.all()# 2. 创建分页器 paginator Paginator(bks, 10)# 3. 获取当前页码cur_page request.GET.get(page, 1)# 4. 根据页码获取页面对象page paginator.page(cur_page)# 5. 返回响应return render(request, bookstore/book.html, locals())模板设计
html
headtitle分页显示/title
/head
body
{% for b in page %}div{{ b.title }}/div
{% endfor %}{% if page.has_previous %}
a href{% url book %}?page{{ page.previous_page_number }}上一页/a
{% else %}
上一页
{% endif %}{% for p in paginator.page_range %}{% if p page.number %}{{ p }}{% else %}a href{% url book %}?page{{ p }}{{ p }}/a{% endif %}
{% endfor %}{% if page.has_next %}
a href{% url book %}?page{{ page.next_page_number }}下一页/a
{% else %}
下一页
{% endif %}
/body
/html使用示例
[rootvm mysite7]# vim mysite7/urls.pypath(test_page, views.test_page,namebook),[rootvm mysite7]# vim mysite7/views.py
...
from django.core.paginator import Paginator
def test_page(request):# 1. 准备要分页的数据list_data [a, b, c, d, e]# 2. 创建分页器paginator Paginator(list_data, 2)# 3. 获取当前页码cur_page request.GET.get(page, 1)# 4. 根据页码获取页面对象page paginator.page(cur_page)# 5. 返回响应return render(request, test_page.html,locals())[rootvm mysite7]# vim templates/test_page.html
html
headtitle分页显示/title
/head
body
{% for b in page %}div{{ b }}/div
{% endfor %}{% if page.has_previous %}
a href{% url book %}?page{{ page.previous_page_number }}上一页/a
{% else %}
上一页
{% endif %}{% for p in paginator.page_range %}{% if p page.number %}{{ p }}{% else %}a href{% url book %}?page{{ p }}{{ p }}/a{% endif %}
{% endfor %}{% if page.has_next %}
a href{% url book %}?page{{ page.next_page_number }}下一页/a
{% else %}
下一页
{% endif %}
/body
/html #访问验证http://192.168.1.11:8000/test_pagecsv文件下载
Django可直接在视图函数中生成csv文件 并响应给浏览器
import csv
from django.http import HttpResponse
from .models import Bookdef make_csv_view(request):response HttpResponse(content_typetext/csv)response[Content-Disposition] attachment; filenamemybook.csvall_book Book.objects.all()writer csv.writer(response)writer.writerow([id, title])for b in all_book: writer.writerow([b.id, b.title])return response响应获得一个特殊的MIME类型text / csv。这告诉浏览器该文档是CSV文件而不是HTML文件响应会获得一个额外的Content-Disposition标头其中包含CSV文件的名称。它将被浏览器用于“另存为…”对话框对于CSV文件中的每一行调用writer.writerow传递一个可迭代对象如列表或元组。
[rootvm mysite7]# vim mysite7/urls.pypath(test_csv, views.test_csv),
[rootvm mysite7]# vim mysite7/views.py
import csv
from django.http import HttpResponse
from .models import Bookdef test_csv(request):# 1. 创建响应对象时指定响应的内容的类型是csvresponse HttpResponse(content_typetext/csv)# 2. 告诉浏览器以附件的方式处理响应数据文件名为mybook.csvresponse[Content-Disposition] attachment; filenamemybook.csv# 3. 获取数据# all_book Book.objects.all()all_book [{id: 1, title: java},{id: 2, title: python},{id: 3, title: php},]# 4. 创建一个csv格式的写入器将数据写入到responsewriter csv.writer(response)# 5. 调用写入器的方式writerow写入一行数据标题writer.writerow([编号, 图书名称])# 6. 写入数据for b in all_book:writer.writerow([b[id], b[title]])return response#访问 http://192.168.1.11:8000/test_csv 产生下载