-- 限制访问次数作业解答 -- -- urls.py 里-- from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index),] -- views.py 里-- from django.shortcuts import render, HttpResponse def index(request): return HttpResponse('index') -- 代码写在哪里? 限制次数 -- 新建文件夹 middleware --> my_middleware.py里 在 settings.py 里注册中间件 'middleware.my_middleware.Throttle' 导入类 from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse import time visit_dict = {} -- 普通版 -- class Throttle(MiddlewareMixin): 节流器 def process_request(self, request): ip = request.META.get('REMOTE_ADDR') now = time.time() # 获取访问的记录 history = visit_dict.get(ip, []) # 根据记录进行判断 [ 10:06:05,10:06:09,10:06:45 ] new = [] for i in history: if now - i < 5: new.append(i) history = new if len(history) >= 3: return HttpResponse('访问频率太快了,你先歇一会') history.append(now) visit_dict[ip] = history -- 优化版-- def process_request(self, request): ip = request.META.get('REMOTE_ADDR') now = time.time() # 获取访问的记录 history = visit_dict.get(ip, []) # 根据记录进行判断 [ 10:06:45,10:06:09,10:06:05, ] while history and now - history[-1] > 5: history.pop() #删除最后一个 if len(history) >= 3: return HttpResponse('访问频率太快了,你先歇一会') history.insert(0, now) visit_dict[ip] = history -- session 版 -- 一个浏览器就是一个用户 def process_request(self, request): now = time.time() #拿到当前时间 # 获取访问的记录 history = request.session.get('history', []) # 根据记录进行判断 [ 10:06:45,10:06:09,10:06:05, ] while history and now - history[-1] > 5: history.pop() if len(history) >= 3: return HttpResponse('访问频率太快了,你先歇一会') history.insert(0, now) request.session['history'] = history 数据库没表 python manage.py migrate 数据库迁移命令 django_session表 一个浏览器就是一个记录
-- html -- ajax参数的问题 $.ajax({ url: '/ajax_test/', 提交地址 type: 'get', 类型 data: { 数据 name: 'alex', 键值对 age: 73, hobby: JSON.stringify(['大保健', 'cnb', '画大饼']) }, success: function (res) { 回调函数 console.log(res) }, error: function (res) { 错误 console.log(res) } }) -- views.py -- from django.conf import global_settings import json from django.http import JsonResponse def ajax_test(request): print(request.POST) hobby = request.POST.get('hobby') # 拿到字符串的东西 hobby = json.loads(hobby) # 反序列化 print(hobby, type(hobby)) # 列表 list # return HttpResponse(json.dumps({'xxx':'xxxx'})) # text/html; charset=utf-8 return JsonResponse({'xxx': 'xxxx'}) # content_type: application/json' # return JsonResponse([],safe=False) # content_type: application/json' 复制代码
上传文件 upload
-- html -- <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" enctype="multipart/form-data"></form> **<form action="" enctype="application/x-www-form-urlencoded"></form>** 删除这行 <input type="file" id="f1"> <button id="b1">上传</button> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> $('#b1').click(function () { var form_obj = new FormData(); #组建FormData对象 form_obj.append('x1', $('#f1')[0].files[0]); #jQuery对象到DOM对象--键,值 $.ajax({ url: '/upload/', type: 'post', data: form_obj, processData:false, #注意 不处理编码方式 contentType:false, #注意 不处理请求头 success: function (res) { alert('OK') } }) }) </script> </body> </html> -- views.py -- 此时注释csrf中间件 def upload(request): if request.is_ajax(): #是的话就返回True file_obj = request.FILES.get('x1') with open(file_obj.name, 'wb') as f: for i in file_obj.chunks(): f.write(i) return HttpResponse('ok') return render(request, 'upload.html')
csrf 校验
-- 发 ajax 能提交 post 请求 -- 保证有cookie {% csrf_token %} 两个作用:一个是隐藏的标签,另一个检查里能看到cookie了 方法一: $.ajax({ url: '/calc/', type: 'post', data: { csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken"]').val() , #属性选择器 i1: $('[name="i1"]').val(), i2: $('[name="i2"]').val(), }, success: function (res) { $('[name="i3"]').val(res) } }) 方法二: 装饰器 from django.views.decorators.csrf import ensure_csrf_cookie #确保访问某个视图有csrf_cookie @ensure_csrf_cookie def func(request): pass 设置请求头 $('#b2').click(function () { $.ajax({ url: '/calc2/', type: 'post', headers:{ 'X-csrftoken': $('[name="csrfmiddlewaretoken"]').val(), }, data: { i1: $('[name="ii1"]').val(), i2: $('[name="ii2"]').val(), }, success: function (res) { $('[name="ii3"]').val(res) } }) }); 推荐以后的用法 -- 引入静态文件,配置静态文件 --批量操作 static --> js -->ajax_setup.js function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } #正则表达式 匹配 $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); 页面引用 <script src="/static/js/ajax_setup.js"></script> 这样每个ajax都可以发送post请求了