Django学习Day11——模型的使用(三)

Django中模型的使用

前面的两篇博客介绍了Django中ORM的基础知识及其使用,我们配合使用的数据库是关系型数据库MySQL,这篇博客我们介绍如何在Django中使用非关系型数据库Redis。

Redis是一个基于内存的非关系型数据库。它通过keyvalue的形式存储。有着多种数据结构,如字符串,列表,集合等。通过redis,我们可以进行数据缓存,防止底层数据库频繁io,提升性能。

因为MySQL数据库中的数据存储于本地磁盘,在MySQL中进行查询,需要在磁盘进行数据的IO操作,当访问量较大的时候,频繁的磁盘IO会降低系统的性能;而Redis是基于内存的数据库,数据存储在内存当中,查询性能较好,如果把频繁读取的数据存在内存当中,可以极大提升系统的性能。

下面介绍如何在Django中使用Redis数据库。

这篇博客主要实现的功能是:编写装饰器函数,对查询函数进行优化,如果内存中存在查询的数据,直接从内存中进行读取;如果内存中不存在查询的数据,则再去本地数据库中进行查询,然后将该数据添加到内存当中,下次查询就可以从内存中获取。

准备工作 

1. 电脑上完成Redis安装,并启动Redis服务

2. 安装Python依赖库,django-redis

3. Django项目中进行相关的配置(settings.py)

使用过程

(1)Django中调用Redis

基于我们安装的Python依赖库django_redis可以进行Redis数据库的调用,使用方式如下:

from django_redis import get_redis_connection
# default为我们在配置文件中的配置信息
conn = get_redis_connection('default')
conn.set('key', 'value', 'valid_time')
result = conn.get('key')

(2)在模型类User中实现普通的查询函数(在本地数据库MySQL中进行查询)

class User(models.Model):
    # 设置姓名为unique;不允许有相同名称的用户,也不允许姓名为空
    name = models.CharField(max_length=50, unique=True, null=False)
    # 用户的年龄不会出现特别大的数值,因此设置为SmallInteger
    age = models.SmallIntegerField(default=0)
    # 电话信息可以允许为空;设置为普通索引,将来可以根据电话进行查询
    phone = models.IntegerField(null=True, db_index=True)
    email = models.EmailField(null=True, default='')
    info = models.TextField(null=True)
    # 创建时间:只在创建时候记录,之后不会进行修改;会自动添加到数据库,不必传入
    create_time = models.DateTimeField(auto_now_add=True)
    # 更新时间:每次修改都会记录修改的时间;会自动添加到数据库,不必传入
    update_time = models.DateTimeField(auto_now=True)

    class Meta:
        # 普通联合索引
        index_together = ['name','age']
        # 唯一联合索引
        unique_together = ['name','phone']

    # classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,
    # 但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。
    @classmethod

    def get(cls, id):
        re = cls.objects.get(id=id)
        return {
            'id':re.id,
            'name':re.name,
            'age':re.age,
            'phone':re.phone,
            'email':re.email,
            'info':re.info,
            'create_time':str(re.create_time),
            'update_time':str(re.update_time)
        }

(3)装饰器函数的实现

from django_redis import get_redis_connection
from functools import wraps
import json

_conn = get_redis_connection('default')

def cache(func):
    @wraps(func)
    # 对于用于修饰类中函数的装饰器,第一个参数应该是obj,对应类中函数的self或者cls
    # *args表示函数实际传入的参数
    def read_from_redis(obj, *args):
        key = func.__name__ + "_" + str(args[0])
        # 首先从内存中获取数据
        result = _conn.get(key)
        if result:
            print('成功从Redis中读取到数据!!!')
            return json.loads(result)
        print('Redis中没有相关数据。。。。')
        result = func(obj, *args)
        add = _conn.set(key, json.dumps(result))
        if add:
            print('成功将数据存储到Redis中!')
        return '装饰器执行完毕'

    return read_from_redis

(4)调用过程如下:

因为User类中的get函数使用@classmethod修饰符进行修饰,所以我们在调用User中的get方法的时候,不需要实例化对象:

第一次调用get函数的时候,因为内存中没有数据,所以会显示上面的信息,此时id=1的数据被添加到内存当中。

这时,我们在Redis数据库中进行查看:

此时,内存中有了id=1的数据,当我们再次调用get函数,获取id=1的用户信息时,会直接从内存中读取,不再进行本地MySQL查找的步骤,如下所示:

参考资料

1、https://coding.imooc.com/class/393.html

2、https://www.runoob.com/python/python-func-classmethod.html

猜你喜欢

转载自blog.csdn.net/ProQianXiao/article/details/113829156