WEB后端服务第17天-Django第七天

WEB后端服务第17天-Django第7天

一、验证码

1.1 验证码方式

  • 图片验证码
  • 滑动验证码
  • 短信验证码
  • 邮箱验证码

1.2 验证码使用场景

  • 防止爬虫程序
  • 防止非人为操作

1.3 基于PIL库实现图片验证码

1.3.1 PIL初步使用
def new_img_code(request):

    # 创建画布
    img = Image.new('RGB', (80, 40), (100, 100, 0))

    # 从画布中获取画笔
    draw = ImageDraw.Draw(img, 'RGB')

    # 创建字体对象和字体颜色
    font_color = (0, 20, 100)
    font = ImageFont.truetype(font='static/fonts/buding.ttf',
                              size=20)

    # 开始画内容
    draw.text((5, 5), '您好', font=font, fill=font_color)

    for _ in range(100):
        x = random.randint(0, 80)
        y = random.randint(0, 40)

        r = random.randint(0, 255)
        g = random.randint(0, 255)
        b = random.randint(0, 255)

        draw.point((x, y), (r, g, b))

    # 将画布写入内存字节数组中
    from io import BytesIO
    buffer = BytesIO()
    img.save(buffer, 'png')  # 写入

    return HttpResponse(content=buffer.getvalue(),
                        content_type='image/png')
#!/usr/bin/python3
# coding: utf-8
import random

def _random_str(start, end):
    return chr(random.randint(start, end))


def new_code_str(len):

    code_str = ''
    for _ in range(len):
        flag = random.randint(0, 2)
        start, end = (ord('a'), ord('z')) if flag == 1 \
            else (ord('A'), ord('Z')) if flag == 2 \
            else (ord('0'), ord('9'))

        code_str += _random_str(start, end)

    return code_str


if __name__ == '__main__':
    print(new_code_str(6))

二、分页器Paginator

2.1 核心类

  • django.core.paginator.Paginator
    • Paginator(object_list, per_page) 创建分页器
    • page(page_num) -> Page 获取page_num的分页对象
    • page_range() -> generator 页号的范围
  • django.core.paginator.Page
    • page.object_list 当前页的数据集
    • page.has_previous 是否有上一页
    • page.previous_page_number 上一页页码
    • page.has_next 是否有下一页
    • page.next_page_number 下一页页码
    • page.number 当前页的页码

2.2 分页器的应用

def order_list(request):
    wd = request.GET.get('wd', '')
    page = request.GET.get('page', 1)

    orders = Order.objects.filter(Q(title__icontains=wd)).all()

    # 分页器Paginator
    paginator = Paginator(orders, 5)
    pager = paginator.page(page)  # 查询第page页

    return render(request, 'list.html', locals())
<table border="1" cellspacing="0" cellpadding="2" width="100%">
    <thead>
    <th>ID</th>
    <th>名称</th>
    <th>单价</th>
    <th>支付状态</th>
    </thead>
    <tbody>
    {% for order in pager.object_list %}
        <tr>
            <td>{{ order.id }}</td>
            <td>{{ order.title }}</td>
            <td>{{ order.price }}</td>
            <td>{{ order.pay_status_title }}</td>
        </tr>
    {% empty %}
        <tr>
            <td colspan="">查无此数据</td>
        </tr>
    {% endfor %}

    </tbody>
</table>
<p style="text-align: center">

    <a {% if pager.has_previous %} href="?page={{ pager.previous_page_number }}&wd={{ wd }}" {% endif %}>&lt;</a>

    {% for p in paginator.page_range %}
        {% if pager.number == p %}
            <a class="page active"> {{ p }} </a>
        {% else %}
            <a class="page" href="?page={{ p }}&wd={{ wd }}"> {{ p }} </a>
        {% endif %}

    {% endfor %}

    <a {% if pager.has_next %} href="?page={{ pager.next_page_number }}&wd={{ wd }}" {% endif %} >&gt;</a>

</p>

中午默写

1. response对象的content属性是什么

content是响应内容, 内容的数据类型可以字符串也可以字节码

如果响应内容是字节码时,需要指定content_type, 如 image/jpg,  image/png

2. response.set_cookie()方法的参数有哪些

set_cookie(key, value, path='/', domain=None, max_age=None,  expires=None)

3. 清除所有session的方法是什么

request.session.clear()

三、类视图 CBV

3.1 概念

Django中视图(View)写法有两种:

  • FBV (Function-based View) 基于函数的视图, 之前都是使用FBV模式。
  • CBV(Class-based View) 基于类的视图, 应用面向对象(OOB)设计思想, 通过继承、重写等相关特性实现业务功能。

3.2 Django提供很多的View

  • View
  • TemplateView
  • RedirectView
  • ListView
  • EditView
  • FormView
  • DetailView
  • DeleteView

3.3 使用的过程

  • 在views.py中定义View的子类,并初始关键属性或重写方法

    在View中处理的流程如下:

    • dispatch(request, *args, **kwargs) 分发请求到get/post/put/delete/等方法处理函数中
    • http_method_not_allowed() 请求方法不允许的响应
    • options() 探测请求方法的Allow信息
  • 在路由的视图函数位置上使用View.as_view()

from stockapp import views

app_name = 'stockapp'
urlpatterns = [
    path('stocks/<stock_id>/',
         csrf_exempt(views.StockView.as_view()),
         name='stocks'),
    path('goods/<wd>/', views.GoodsView.as_view(), name='goods'),
    path('query/<wd>/', views.QueryView.as_view(), name='query')
]
class StockView(View):
    def dispatch(self, request, *args, **kwargs):

        return super().dispatch(request, *args, **kwargs)

    def get(self, request, **kwargs):
        # 获取请求路径中变量内容
        stock_id = kwargs.get('stock_id')
        return render(request, 'stock/list.html', locals())

    def post(self, request):
        return HttpResponse('Post请求')

四、中间件 Middleware

4.1 概念

中间件基于AOP(面向切面编程)设计思想, 目的扩展业务功能,即不修改原业务基础之上,增加新的功能,类似于装饰器。中间件有很多的使用场景: 验证权限、限制ip(黑名单)、限制请求次数、跨域请求、访问日志/统计、记录错误信息。

Django的中间件有五个勾子函数【重要】:

  • process_request(request) 从django框架到urls路由过程
  • process_view(request, callback, callback_args, callback_kwargs) 从urls路由到view视图函数的过程
  • **process_template_response() ** 在view视图中渲染模板的过程【不常用】
  • process_exception(request, exception) 从请求到响应的整过程,如果发生了异常,则会被此函数处理
  • process_response(request, response) 从视图函数中向Django响应数据时, 即返回 HttpResponse()对象后

4.2 自定义中间件

中间件的基本类: django.utils.deprecation.MiddlewareMixin

在项目的目录下,创建middleware包和check_login.py脚本,内容如下:

from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin


class CheckLoginMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 从请求到路由urls过程,触发此函数
        dontfilters = ['/user/login/', '/user/code/']
        if request.path not in dontfilters:
            # 验证用户是否登录
            if not request.COOKIES.get('token'):
                return HttpResponse('<h3>Login</h3><form><input><button>Login</button></form>')

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print('---CheckLoginMiddleware--', 'process_view')
        # callback 是调用的view函数
        # 新增一个关键参数, 类似于匹配路由 stock/<stock_id>/<page>/
        # callback_kwargs['page'] = request.GET.get('page', 1)
        print(callback, callback_args, callback_kwargs)

    def process_response(self, request, response):
        print('---CheckLoginMiddleware--', 'process_response')
        return response # 必须返回响应对象

在settings.py的注册中间件类

MIDDLEWARE = [
		'...'
    'middleware.check_login.CheckLoginMiddleware',
]

五、Django日志

5.1 Django日志LOGGING的组成部分

  • 日志的版本号 version
  • 日志的格式化 formatters
  • 日志的处理器 handlers
  • 日志的记录器 loggers, 默认存在"django.server", “django.request”
  • 日志的过滤器 filters

5.2 配置日志

在settings.py脚本中配置,内容如下:

# 配置Django的日志
LOGGING = {
    'version': 1.0,
    'formatters': {
        'base': {
            'format': '[%(asctime)s  %(name)s ] %(message)s',
            'datefmt': '%Y-%m-%d %H:%M:%S'
        }
    },
    'handlers': {
        'out': {
            'class': 'logging.StreamHandler',
            'level': 'INFO',
            'formatter': 'base'
        },
        'file': {
            'class': 'logging.FileHandler',
            'level': 'WARNING',
            'formatter': 'base',
            'filename': f'{BASE_DIR}/warn.log'
        }
    },
    'loggers': {  
        # 日志记录器 django.server
        'django.server': {
            'handlers': ['out', 'file'],
            'level': 'CRITICAL',
            'propagate': False
        },
        'mylogger': {
            'handlers': ['out', 'file'],
            'level': 'INFO',
            'propagate': False
        }
    }
}

5.3 使用日志

import logging

logging.getLogger('mylogger').error('请求发生错误')

5.4 扩展: Django默认日志配置源码

源码脚本: django.utils.log.py

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'formatters': {
        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[%(server_time)s] %(message)s',
        }
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
        },
        'django.server': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'django.server',
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
        },
        'django.server': {
            'handlers': ['django.server'],
            'level': 'INFO',
            'propagate': False,
        },
    }
}

六、缓存Cache

6. 1 配置缓存

6.1.1 文件缓存
# 配置缓存Cache
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': f'{BASE_DIR}/mycache',
        'TIMEOUT': 300,
        'OPTIONS': {
            'MAX_ENTRIES': 500,
            'CULL_FREQUENCY': 3
        }
    }
}

6.2 使用缓存

6.2.1 文件缓存的使用

导包

from django.core.cache import cahce

增加

cache.set(key, value, timeout)
cache.add(key, value,timeout, version)

读取

cache.has_key(key)
value = cache.get(key)

删除

cache.delete(key)

七、作业

1. 练习课堂code并总结笔记

2. 基于CBV优化验证码及用户登录与注册功能

3. 优化页面缓存2秒

4. 通过中间件验证用户是否登录,未登录直接跳转到登录页面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值