Django-- (六) Django高级开发

1、自定义过滤器

Django提供了很多过滤器,但有时并不能满足我们的需求,这时候就需要自定义过滤器来实现某种功能。

1.1 步骤

1、创建templatetags包

名字是固定的,不能随意改动

2、 在templatetags包里创建文件,用来存放过滤器函数,文件名字可以任意。

3、编写过滤器函数

from django.template import Library

register = Library()  # 实例化模板库


@register.filter  # 用来注册过过滤器的装饰器
def phone_filter(phone):
    """接收并返回过滤的结果函数"""
    result = phone[:3]+"***"+phone[-4:]  # 对号码进行处理
    return result  # 返回过滤结果

4、使用过滤器

{% load  buyer_filter %}  <!-- 加载过滤器 -->

<p class="text-center">{% phone|phone_filter %}</p>  <!-- 使用phone_filter过滤器 -->

2、自定义实体类管理器

通常我们通过模型的objects方法调用查询的方法,实质上,objects是Django模型动态生成的一个查询类,这个查询类继承了models.Manager。

2.1 步骤

1、定义类

from django.db.models import Manager


class SellerManager(Manager):
    """自定义管理器类"""

    def get_name(self, id):
        """根据id查询并返回结果名字"""
        return Seller.objects.get(pk=id).name

2、将定义的类复制到objects

class Seller(models.Model):
    """seller卖家"""
    name = models.CharField(max_length=64)
    password = models.CharField(max_length=64)
    nickname = models.CharField(max_length=64, null=True)
    ...
    objects = SellerManager()  # 自定义manager管理器对象,名字是objects

1个实体类只有能有1个名字是objects的管理器,如果定义其他管理器了,objects就没有。

3、测试

3、中间件

中间件是处理Django请求和响应的框架级别的钩子,它是一个轻量、低级别的插件系统,用于全局范围内改变Django的输入和输出,每一个中间件都有固定的功能,使用需要很谨慎。中间件尽可能的解决了项目代码冗余和代码一致性问题。简单的讲django中间件是django提供给用户可以影响全局请求和响应的接口。

3.1 中间件方法及使用

中间件在使用前需要settings中设置

中间件有五个方法,下图为各个中间件的执行顺序:

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

class MyMiddleware(MiddlewareMixin):
    """中间件"""

    def process_request(self, request):
        """
        请求开始,在视图函数之前执行的。
        :param request: 包含请求信息的请求对象
        :return:
        """
        print("process_request")

    def process_view(self, request, callback, callbackarg, callbackkwargs):
        """
        视图函数之前,process_request 方法之后执行的
        :param request:包含请求信息的请求对象,但有可能被process_request处理
        :param callback:处理请求的函数
        :param callbackarg:元组参数
        :param callbackkwargs:字典参数
            参数:通过路由中的正则匹配到内容
                元组参数:正则中使用组匹配
                字典参数:正则中使用组匹配 + 别名
        :return:
        """
        print("process_views")

    def process_exception(self, request, exception):
        """错误"""
        print("process_exception")

    def process_template_response(self, request, response):
        """视图结束,模板开始渲染"""
        print("process_template_response")
        return response

    def process_response(self, request, response):
        """响应结束"""
        print("process_response")
        return response
3.1.1 process_request (常用)

请求开始,在视图函数之前执行的。可以用来禁止被封的ip访问

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

class MyMiddleware(MiddlewareMixin):
    """自定义中间件"""

    def process_request(self, request):
        """
        :param request: 包含请求信息的请求对象
        :return:
        """
        print("process_request")
        ips = ["127.0.0.1"]
        # 获取IP
        ip = request.META.get("REMOTE_ADDR")
        # 判断
        if ip in ips:
            # 响应,真实环境可以选择渲染到一个页面
            return HttpResponse("你已经被禁止了...")

3.1.2 process_views

视图函数之前,process_request 方法之后执行的,也可以理解为视图预处理

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

class MyMiddleware(MiddlewareMixin):
    """自定义中间件"""

    def process_view(self, request, callback, callbackarg, callbackkwargs):
        """
        :param request:包含请求信息的请求对象,但有可能被process_request处理
        :param callback:处理请求的函数
        :param callbackarg:元组参数
        :param callbackkwargs:字典参数
            参数:通过路由中的正则匹配到内容
                元组参数:正则中使用组匹配
                字典参数:正则中使用组匹配 + 别名
        :return:
        """
        print("process_views")
        print(callback)
        print(callbackarg)
        print(callbackkwargs)
        if int(callbackkwargs.get("version").split("v")[-1]) <= 1:
            return HttpResponse("版本太低")

3.1.3 process_exception

视图发生错误时执行的函数,一般可以用来记录日志

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

class MyMiddleware(MiddlewareMixin):
    """自定义中间件"""

    def process_exception(self, request, exception):
        print("process_exception")
        print(exception)
        import os
        import time
        now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        from shop.settings import BASE_DIR
        file = os.path.join(BASE_DIR, "error.log")
        content = f"[{now_time}]:{str(exception)}"
        with open(file, 'w', encoding='utf-8') as fp:
            fp.write(content)
        return HttpResponse("错误")

3.1.4 process_template_response

视图结束,模板开始渲染。默认不会执行,它对视图函数格式是有要求的:视图函数的返回响应对象必须有render方法。

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

class MyMiddleware(MiddlewareMixin):
    """自定义中间件"""

    def process_template_response(self, request, response):
        print("process_template_response")
        return response
from django.template import loader

def skip(request):
    print("测试路由")
    # 创建响应对象
    response = HttpResponse()
    # 准备数据字典
    con = {"name": "laowang"}

    # 内部render方法
    def myrender():
        print("skip内的myrender方法")
        # 加载模板
        template = loader.get_template("store/skip.html")
        # 设置响应内容,template.render(con)将变量渲染到模板中,得到渲染后的html
        response.content = template.render(con)
        # 返回响应对象
        return response

    # 给响应对象设置render
    response.render = myrender
    return response
<!--skip.html-->
<p>{{ name }}</p>

3.1.5 process_response(常用)

响应结束,可以对所有的返回结果做处理,例如:设置响应头,设置返回的数据类型,设置cookie、session,同一返回的格式。

from django.utils.deprecation import MiddlewareMixin

class MyMiddleware(MiddlewareMixin):
    """自定义中间件"""
    
    def process_response(self, request, response):
        print("process_response")
        response.set_cookie("test", "process_response")
        return response

4、缓存

Django用来做动态网站,每次请求页面都需要进行各种运算,然后从数据库当中取得数据,染好呈现到业务逻辑。从处理开销的角度来看,这个成本比在文本里读取内容大很多。这个时候,对常用的数据存放到独立的一个容器当中,当用户请求,不再直接数据库去取数据,而是先从容器里找。这种技术叫做缓存技术。这个容器可以是内存,文件,数据库或者专业缓存服务器(Memcache)。

缓存的优点:

提高访问速度,降低服务器的压力(主要是数据库相关)。

使用场景:

经常做查询,不要求实时数据,数据量大并且业务复杂,例如电商的首页,上月的话费信息等等

内存缓存是缓存手段当中最快的,但是有内存溢出漏洞。

文件缓存是缓存当中性价比最高,但是有安全漏洞。

数据库缓存,再创建一个表存放经常查询的数据,设计难度比较高。

Django默认没有设置缓存,需要自己设置,可以在全局配置中找缓存配置

4.1 内存缓存

配置信息

# 缓存到内存
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',  # 缓存后台使用的引擎
        'LOCATION': 'my_cache',  # 缓存名称
        'TIMEOUT': 300,  # 缓存超时时间(默认300秒,None表示永不过期,0表示立即过期)
        'OPTIONS': {
            'MAX_ENTRIES': 300,  # 最大缓存记录的数量(默认300)
            'CULL_FREQUENCY': 3,  # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        },
    }
}

4.2 文件缓存

# 缓存到文件
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',  # 缓存后台使用的引擎
        'LOCATION': os.path.join(BASE_DIR, "file_cache"),  # 缓存到本地的文件夹
        'TIMEOUT': 300,  # 缓存超时时间(默认300秒,None表示永不过期,0表示立即过期)
        'OPTIONS': {
            'MAX_ENTRIES': 300,  # 最大缓存记录的数量(默认300)
            'CULL_FREQUENCY': 3,  # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        },
    }
}

4.3 数据库缓存

需要创建数据库,在命令行中输入下面命令创建数据库

python manage.py createcachetable
# 此缓存将内容保存至数据库中
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',  # 缓存后台使用的引擎
        'LOCATION': 'table_cache',  # 数据库表,表名自动生成
        'TIMEOUT': 300,  # 缓存超时时间(默认300秒,None表示永不过期,0表示立即过期)
        'OPTIONS': {
            'MAX_ENTRIES': 300,  # 最大缓存记录的数量(默认300)
            'CULL_FREQUENCY': 3,  # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
        },
    }
}

4.4 memcache缓存

4.4.1 安装memcache服务器

下载解压后以管理员的身份进入命令窗口,切换到解压后的文件夹下执行下面的命令,安装memcache

memcached.exe -d install

4.4.2 安装python memcached模块
pip install python-memcached
4.4.3 配置
# 此缓存将内容保存至Memcached中
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',  # 缓存后台使用的引擎
        'LOCATION': '127.0.0.1:11211',  # Memcached地址
        'TIMEOUT': 300,  # 缓存超时时间(默认300秒,None表示永不过期,0表示立即过期)
    }
}

4.5 缓存的使用

缓存技术是提高访问效率,降低服务器压力的一种网站调优手段。一般我们都是使用memcache缓存。

4.5.1 缓存原理图解:

4.5.2 视图中使用
from django.views.decorators.cache import cache_page

@cache_page(10)
def test_cache(request):
    print("*" * 100)
    now = datetime.now().strftime("%H:%M:%S")
    return HttpResponse(now)

4.5.3 路由中使用
from django.urls import path
from django.views.decorators.cache import cache_page
from store.views import test_cache

urlpatterns = [
    path("test_cache/", cache_page(10)(test_cache)),  # 单位是秒
]

4.5.4 html中使用
def test_cache(request):
    print("*" * 100)
    now = datetime.now().strftime("%H:%M:%S")
    return render(request, "store/test_cache.html", locals())
<!--test_cache.html-->

{% load cache %}

<p>现在时间{{ now }}</p>
<hr>

{% cache 10 test_cache %}  {# 单位是秒,名字随意起 #}
<p>缓存时间{{ now }}</p>
{% endcache %}

4.5.5 全局使用

全局使用反而给memcache服务增添了压力,一般不采用这种方法

4.5.6 底层cache使用(推荐使用)

1、导包

from django.core.cache import cache

2、方法

get 获取缓存 cache.get(key)

set 设置缓存 cache.set(key,value,timeout)

delete 删除缓存 cache.delete(key)

3、流程

请求数据,判断缓存中是否存在数据,如果有,直接返回数据,如果没有,从数据中查询,设置缓存返回结果。一般缓存的数据更新的话也要重新设置,避免无效或错误信息一直给用户显示。

4、案例:缓存首页的商品数据

from django.core.cache import cache
from store.models import GoodsType

def set_cache():
    """查询并设置缓存"""
    goods_type = GoodsType.objects.all()
    cache.set("goods_type_cache", goods_type, 60 * 60 * 24)
    print("*" * 100)


@login_check(url)
def index(request):
    goods_type = cache.get("goods_type_cache")
    if not goods_type:
        # 查询并设置缓存
        set_cache()
    return render(request, "buyer/index.html", locals())

新增商品时重新设置缓存

@login_check(url)
def goods(request):
    if request.method == "POST":
        # 获取post提交的数据
        name = request.POST.get("name")
        price = request.POST.get("price")
        number = request.POST.get("number")
        goods = Goods()
        goods.name = name
        goods.price = price
        goods.number = number
        goods.save()
        # 更新成功后重新设置缓存
        from buyer.views import set_cache
        set_cache()
        return redirect("/store/goods/")
    return render(request, "store/goods.html", locals())

适合人群: 1、具有一定Python语言基础,有一定的web前端基础,想要深入学习Python Web框架的朋友; 2、学习完“跟着王进老师学开发Python篇”“跟着王进老师学Web前端开发”的朋友; 3、有Django基础,但是想学习企业级项目实战的朋友; 4、喜欢 Django 框架并想深入研究的朋友; 5、有一定的数据库基础 课程目标: 本系列课程是从零基础开始并深入讲解Django,最终学会使用Django框架开发企业级的项目。课程知识点全网最详细,项目实战贴近企业需求。本系列课程除了非常详细的讲解Django框架本身的知识点以外,还讲解了web开发中所需要用到的技术,学完本系列课程后,您将独立做出一个具有后台管理系统,并且前端非常优美实用的网站。对于从事一份Python Web开发相关的工作简直轻而易举。 课程内容: 一、融汇贯通 将Python语言和Django基础知识,以实际应用为媒介,有机组织、融汇贯通。让你的理论与实践结合起来,由知道变成会用。使用了大量的Django高级特性和Bootstrap前端框架,展示了真实的项目部署过程。 二、贴近实战 本系列课程为项目实战:超市前端收银系统的开发,项目包含了如下几个模块:系统登录页面、收银模块、管理人员的主界面、收银明细查询。从零开始展示了开发过程。包含了开发前的需求分析、数据库的设计、前端页面的准备、登录模块的实现、收银模块的实现、主界面的动态加载、收银明细的查询。课程具有极强的实战性。
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页