Django学习总结(Week01-结)

关于request.Files.get(‘head‘)取不到值的问题,需要在前端把表单的enctype设置为multipart/form-data

这样用户头像的修改和学生头像上传问题一起解决了。

<form action="{% url ‘app:students‘ %}" method="post" enctype="multipart/form-data">

值得一提的是在保存图片时,models中的

s_head = models.ImageField(upload_to=‘Image/student‘, default=‘Image/default.jpg‘)  # 学生照片

是以settings中设置的MEDIA_ROOT作为根路径的,所以在使用时记得在settings中注册:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, ‘static‘)
]

MEDIA_ROOT = os.path.join(BASE_DIR, ‘static/media‘)

学生管理页面因为缓存问题在更新时不能第一时间把最新数据呈现出来,那只要在更新时删除缓存就行了。

首先在接收到get请求时判断数据库中是否有该页面的缓存,有则直接返回该缓存。

result = cache.get(‘students‘)

if result:
  return HttpResponse(result)

否则在返回页面前将页面数据保存到缓存数据库中。

response = render(request, ‘student.html‘, data)
cache.set(‘students‘, response.content, timeout=60)

然后在更新数据时删除该页面的缓存,这个用一个函数实现:

def delCache(key):
    if cache.get(key):
        cache.delete(key)

这个方法是用django内置的数据库缓存,性能相对较低,尝试用redis实现

首先安装redis:

pip install django-redis
pip install django-redis-cache

redis-server启动redis服务。(PC中要安装redis)

在settings中注册

CACHES = {
    ‘default‘: {
        ‘BACKEND‘: ‘django.core.cache.backends.db.DatabaseCache‘,
        ‘LOCATION‘: ‘my_cache_table‘,
        ‘TIMEOUT‘: 60 * 5
    },
    ‘redis_backend‘: {
        ‘BACKEND‘: ‘django_redis.cache.RedisCache‘,
        ‘LOCATION‘: ‘redis://127.0.0.1:6379/1‘,
        ‘OPTIONS‘: {
            ‘CLIENT_CLASS‘: ‘django_redis.client.DefaultClient‘,
        }
    }
}

使用时涉及到一个多缓存问题,也很简单,用caches就行了。

cache = caches[‘redis_backend‘]

接下来是中间件的使用练习。

在工程目录下新建middleware目录

新建一个middle.py文件,创建一个继承了MiddlewareMixin的类:

from django.utils.deprecation import MiddlewareMixin

class StdMiddle(MiddlewareMixin):
    pass

在settings中注册中间件:

中间件中有五个方法可以定义:

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

process_request

  • 客户端发来请求与路由匹配执行之前执行
  • 返回值是None时,继续向后执行下一个中间件的process_request或路由映射
  • 返回值是HttpResponse对象时,不执行路由与views函数,直接执行该中间件与其之前的process_response,倒序执行

process_view

  • 在执行完所有中间件的process_request与路由映射之后,views函数执行之前执行
  • 执行顺序依然从第一个中间件到最后一个中间件
  • callback参数为执行的views函数
  • callback_args, callback_kwargs为views函数的参数
  • 返回值是None时,继续向后执行下一个中间件的process_view或views函数
  • 返回值是HttpResponse对象时,不执行views函数,直接执行所有中间件的process_response,倒序执行

process_template_response

  • 视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)时,才被执行(并不是views函数最后返回render对象)
  • 在views执行之后,process_exception执行之前执行
  • 返回值必须是response
  • 倒序执行

process_exception

  • process_exception用于捕捉views函数中的异常
  • 在process_response之前执行
  • exception是views函数中产生的异常对象
  • 返回值是None时继续正常执行
  • 返回值是HttpResponse对象:不再执行后面的process_exception方法,直接执行process_response
  • 倒序执行

process_response

  • 在response返回给客户端之前执行,也就值最后经过
  • 必须返回HttpResponse对象

上面一段讲解来自https://www.cnblogs.com/sfencs-hcy/p/10465967.html

按照我的需求,我要在执行指定的视图函数时,判断用户是否登录,然后进行相应的操作,

所以这里应该定义process_view函数,通过request.META.get(‘PATH_INFO‘)获取请求的路由,判断是否在我指定的路由列表中,然后进行相应的操作,代码实现:

class StdMiddle(MiddlewareMixin):
    PATH_LIST = [‘/center/‘, ‘/students/‘, ‘/getStudent/‘, ‘/delStudent/‘]

    def process_request(self, request):
        print(request.META)

    def process_view(self, request, view_func, view_args, view_kwargs):
        ‘‘‘
        :param request: 浏览器发来的 request 请求对象
        :param view_func: 将要执行的视图函数的名字
        :param view_args: 将要执行的视图函数的位置参数
        :param view_kwargs: 将要执行的视图函数的关键字参数
        :return:
        ‘‘‘
        account = request.session.get(‘account‘)
        if request.META.get(‘PATH_INFO‘) in self.PATH_LIST:
            if account is None:  # 没有session则返回到登录页面
                return redirect(reverse(‘app:index‘))

        elif request.META.get(‘PATH_INFO‘) == ‘/index/‘:
            if account:  # 有session则直接进入个人中心
                return redirect(reverse(‘app:center‘))

中间件实现频率控制。

思路:在客户端请求时get客户端的ip,在缓存中申请一个列表,里面存放的是发送请求时的时间,

然后用当前请求的时间-最早请求的时间,如果这个时间超过了指定的时间,则把最早请求的时间从列表中删除

如果没有超过,那么列表的长度就会+1,在这之后进行判断,如果长度超过了我们规定的次数,那么就拒绝本次访问,否则把列表存到缓存中。

代码实现:

    def process_request(self, request):
        ip = request.META.get(‘REMOTE_ADDR‘)
        cache = caches[‘redis_backend‘]
        requestCount = cache.get(ip, [])

        while requestCount and time.time() - requestCount[-1] > 30:
            requestCount.pop()
        requestCount.insert(0, time.time())

        if len(requestCount) >= 10:
            return HttpResponse(‘小爬虫回家吧‘)

        cache.set(ip, requestCount, timeout=60 * 5)

30秒内只能请求十次。如果是反爬虫可以设置一个黑名单用户表,如果超过了规定次数就把ip加到表中,然后每次请求时查询黑名单表,看ip是否在表中,这样就实现了简单的反爬虫。

使用process_exception来处理异常:

    def process_exception(self, request, exception):

        return redirect(reverse(‘app:index‘))

这周最后学习了验证码登录,在登录页面添加一个验证码。

使用PIL进行绘图,首先获得一个四位的验证码:

def getCode():
    source = ‘qwertyuioplkjhgfdsazxcvbnm1234567890POIUYTREWQASDFGHJKLMNBVCXZ‘
    code = ‘‘

    for i in range(4):
        code += random.choice(source)

    return code

使用PIL绘图,并把得到的image对象存到内存中,传到前端

def getCheckCode(request):  # 验证码生成
    code = getCode()
    mode = ‘RGB‘
    size = (200, 100)
    color_bg = (getColor(), getColor(), getColor())

    image = Image.new(mode=mode, size=size, color=color_bg)
    imageDraw = ImageDraw(image, mode=mode)
    imageFont = ImageFont.truetype(settings.FONT_PATH, 80)

    for i in range(4):
        imageDraw.text(xy=(50*i, 0), text=code[i], font=imageFont, fill=(getColor(), getColor(), getColor()))

    for i in range(1000):
        imageDraw.point(xy=(random.randrange(200), random.randrange(100)), fill=(getColor(), getColor(), getColor()))

    fp = BytesIO()
    image.save(fp, ‘png‘)
    request.session[‘checkCode‘] = code
    return HttpResponse(fp.getvalue(), content_type=‘image/png‘)

在前端加上一个Img标签即可,效果图:

......

原文地址:https://www.cnblogs.com/ylnx-tl/p/12588253.html

时间: 2024-11-02 10:30:14

Django学习总结(Week01-结)的相关文章

Django学习---多人博客项目(2)

Django学习---多人博客项目(2) ? 上一部分内容完成了博客项目的搭建,以及博客标题和博客内容的展示,熟悉了Django的使用,下面,接着实现用户管理部分功能. 一.自定义模板和静态文件的位置 (1)自定义模板的位置 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 当前文件路径的上两级文件路径--即是根目录 TEMPLATES = [ { 'BACKEND': 'django.templat

Django 学习笔记(七)数据库基本操作(增查改删)

一.前期准备工作,创建数据库以及数据表,详情点击<Django 学习笔记(六)MySQL配置> 1.创建一个项目 2.创建一个应用 3.更改settings.py 4.更改models.py 5.同步数据 二.安装IPython方便debug sudo apt-get install ipython3 安装成功后用python manage.py shell 会自动进入Ipython交互解释器中,没有安装Ipython只有前两行代码,只进入到Python shell 中. Python 3.5

Django学习笔记 Day One

Time:2016年01月01日21:38:55 Description: 从今天开始我开始写我的Django学习笔记,因为网络上太多太杂乱的文章,不成系统,还有就是太多的培训机构讲述的东西过于简单,没有深入讲解Django,算是自己的一个小笔记吧,主要参考的是Django1.8的官方文档,地址:www.djangoproject.com,一家之言,大神勿喷! Content: Day One. First exploration of django? 我们在Web开发过程中,常常会遇到编写重复

Django学习笔记(三)—— 模型 model

疯狂的暑假学习之 Django学习笔记(三)-- 模型 model 参考:<The Django Book> 第5章 1.setting.py 配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.', # 用什么数据库管理系统 'NAME': '', # 数据库名称,如果用sqlite,要写完整路径 'USER': '', # 如果用sqlite,这个不用写 'PASSWORD': '', # 如果用sqlite,这个不用写

django学习之Model(四)MakingQuery

上一篇写到MakingQuey中的filter,本篇接着来. 10)-扩展多值的关系 如果对一个ManyToManyField或ForeignKey的表进行filter过滤查询的话,有2中方法可以用.分别是: #1 Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008) #2 Blog.objects.filter(entry__headline__contains='Lennon')

Django学习笔记(五)—— 表单

疯狂的暑假学习之  Django学习笔记(五)-- 表单 参考:<The Django Book> 第7章 1. HttpRequest对象的信息 request.path                                 除域名以外的请求路径,斜杠开头                      "/hello/" request.get_host()                      主机名                              

django学习笔记

用的windows操作系统,真是蛋疼啊,等赚了钱,我真要买一台苹果或者换个12寸的小本,用ubuntu,所以一下命令都是windows的,真心蛋疼啊,为什么没有自动补完啊 首先,随便下个django. 然后,进入命令行,进入django的文件夹键入如下命令 django>python setup.py install 经过短时间的等待,安装完成. 然后随便建一个文件夹,比如myproject,命令行进入文件夹,然后输入如下命令,一个django项目就算建好了 myproject>django-

django学习之Model(五)MakingQuery

接着上篇. 10-一次更新多个对象 有时想要对QuerySet中的所有对象的某一个field来设定一个值,这时候可以像下边这样用update(): # Update all the headlines with pub_date in 2007. Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same') 这样使用的update()只能是没有关联关系的model或者有ForeignKey的

Django学习笔记(四)—— Admin

疯狂的暑假学习之  Django学习笔记(四)-- Admin 参考:<The Django Book> 第6章 Django 可以使用admin自动创建管理界面. 1. 配置 django-admin.py startproject 创建的项目,如果没有注解掉默认的配置,python manage.py syncdb 创建用户后,直接 http://xxxxxx/admin 输入密码即可进入. 如果修改了配置文件,保证将 django.contrib.admin 加入setting.py 中

Django 学习笔记之三 数据库输入数据

假设建立了django_blog项目,建立blog的app ,在models.py里面增加了Blog类,同步数据库,并且建立了对应的表.具体的参照Django 学习笔记之二的相关命令. 那么这篇主要介绍往数据库中添加数据,django默认的是sqlite3数据库. 在建立完django_blog项目后,不要忘了把 blog 加入到 settings.py 中的 INSTALLED_APPS 中. 一.同步数据库,创建相应的表 具体的参照Django 学习笔记之二的的同步数据库. 二.数据输入 下