Django学习10:Django高级

本文深入探讨了Django的高级特性,包括处理静态文件、中间件的工作原理及自定义中间件的创建,文件上传的实现,分页操作的Paginator对象,以及如何利用Celery进行异步任务处理以优化用户体验。通过实例详细讲解了每个概念,帮助读者理解并掌握Django的高级应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Django高级

静态文件

包含工程中的CSS, JS, 图片,Json等文件

{% load static from staticfiles %}
<!DOCTYPE html>
<html>
    <script type = 'text/javascript' src = '{% static "js/nian.js" %}'></script>
</html>

中间件

概述

一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入和输出。每一个中间组件都是一个独立的Python类

自定义中间件

  1. 工程目录下创建名为middlewares的目录
  2. 在middlewares目录下创建项目目录同名的目录
  3. 在上一步创建的目录下创建中间件的Py文件
  4. 在文件中定义中间件类
  5. 在settings.py文件中的MIDDLEWARE中添加’middlewares.myApp.myMiddle.MyMiddle’
  6. 注意:使用中间件,可以干扰整个处理过程,每次请求都会执行中间件的这些方法

方法

  1. __init__.py:无需任何参数,服务器响应第一个请求时调用一次,用于确认是否启用当前中间件
  2. process_request(request):执行试图之前被调用,每个请求都会调用,返回None或者HttpResponse对象
  3. process_view(request, view_func, view_args, view_kwags):执行视图之前被调用,每个请求上都会调用,返回None或者HttpResponse
  4. process_template_response(request, response):在视图刚好执行完毕之后被调用,每个请求中都会调用,返回实现了render方法的响应对象
  5. process_response(request, response):响应浏览器之前被调用,每个请求都会调用,返回HttpResponse对象
  6. process_exception(request, exception):当视图抛出异常时调用,每个请求都会调用,返回HttpResponse对象

示例

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

class MyMiddle(MiddlewareMixin):
  def process_request(self, request):
    if request.COOKIES.get('nian') == 'bad':
      return HttpReponse('Nice day')

上传文件

概述

当Django在处理文件时,文件的 数据会被保存在request.FILES

服务器接收上传文件

在static目录下创建名为media的目录

MEDIA_ROOT = os.path.join(BASE_DIR, r'static\media')

# html代码
<form action = '/upfile/' method = 'post' enctype = 'multipart/form-data'>
    <input type = 'file' name = 'file'>
    <input type = 'submit' value = '提交'>
</form>

# 视图函数
import os
from django.conf import settings
def upfile(request):
  if request.method == 'GET':
    return render(request, 'upfile.html')
  else:
    # 保存文件
    for key in request.FILES:
      fileObj = request.FILES[key]
      filePath = os.path.join(settings.MEDIA_ROOT, fileObj.name)
      print(filePath)
      with open(filePath, 'wb') as fp:
        for c in fileObj.chunks():
          fp.write(c)
  return HttpResponse('收到文件')

分页

Paginator对象

  1. 创建对象:Paginator(列表, 每页数据量)
  2. 属性:
    count:对象总数
    num_pages:页面总数
    page_range:页码列表
  3. 方法:
    page(num):创建page对象,num为要获取数据的页码,从1开始
  4. 异常:
    InvalidPage:当向page传入一个无效的页码
    PageNotAnInteger:当传入的页码不是一个整数
    EmptyPage:当向page传入是有效值但页面上没有任何数据

Page对象

  1. 创建page对象:Paginator对象的page方法创建
  2. 属性:
    object_list:当前页上的所有对象列表集合
    number:当前页的页码
    paginaor:引用创建该对象的Paginator对象
  3. 方法:
    has_next:如果有下一页,返回True
    has_previous:如果有上一页,返回True
    has_other_pages:如果有上一页或者下一页,返回True
    next_page_number:如果有下一页则返回下一页的页码,如果下一页不存在则抛出InvaidPage异常
    previous_page_number:如果有上一页则返回上一页的页码,如果上一页不存在则抛出InvaidPage异常
    len:返回当前页面对象的个数
  4. 示例
# html代码:
       <!DOCTYPE html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <title>分页</title>
       </head>
       <body>
           <ul>
               {% for stu in stus %}
                   <li>{{ stu.sname }}</li>
               {% endfor %}
           </ul>

           {% if stus.has_previous %}
               <a href="/students/{{ stus.number | add:-1 }}">上一页</a>
           {% else %}
               上一页
           {% endif %}

           {% for index in stus.paginator.page_range %}
               {% if index == stus.number %}
                   {{ index }}
               {% else %}
                   <a href="/students/{{ index }}">{{ index }}</a>
               {% endif %}
           {% endfor %}

           {% if stus.has_next %}
               <a href="/students/{{ stus.number | add:1 }}">下一页</a>
           {% else %}
               下一页
           {% endif %}
       </body>
       </html>
   # 视图代码:
   from django.core.paginator import Paginator
   def students(request, page):
       allStudents = Students.object3.all()

       # 创建Paginator对象
       paginator = Paginator(allStudents, 5)  # 每页5条数据
       stus = paginator.page(page)

       # 如果有下一页,返回True
       print(stus.has_next())

       # 如果有上一页,返回True
       print(stus.has_previous())

       # 如果有上一页或者下一页返回True
       print(stus.has_other_pages())

       # 如果有下一页返回下一页页码,没有抛出异常
       print(stus.next_page_number())

       print(stus.previous_page_number())

       # 返回当前对象的个数
       print(len(stus))

       return render(request, 'students.html', {'stus':stus})

ajax

   # 视图代码:
   from django.http import JsonResponse
   def ajax(request):
       return render(request, 'ajax.html')

   def ajax2(request):
       if request.method == 'GET':
           return render(request, 'ajax.html')
       else:
           # 接受到ajax请求
           stus = Students.object3.all()
           lis = []

           for stu in stus:
               lis.append({'name':stu.sname, 'age':stu.sage})
           return JsonResponse({'data':lis})

   # html代码:
   {% load staticfiles %}
   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <title>展示学生信息</title>
       <script type="text/javascript" src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
   </head>
   <body>
       <button id="btn">展示学生信息</button>
       <div id="box"></div>

       <script type="text/javascript">
          $('#btn').bind('click', function () {
            $.ajax({
                   type:'post',
                   url:'/ajax2/',
                   dataType:'json',
                   success:function (data, status) {
                       console.log(data)
                       var arr = data['data']
                   }
               })
          })
       </script>
   </body>
   </html>

富文本
pip install django-tinymce
在admin站点中使用:

   # 配置settings.py
   INSTALLED_APPS = [
           'django.contrib.admin',
       'django.contrib.auth',
       'django.contrib.contenttypes',
       'django.contrib.sessions',
       'django.contrib.messages',
       'django.contrib.staticfiles',
       'myApp',
       'tinymce',
       'djccelery',
   ]

   # 富文本配置
   TINYMCE_DEFAULT_CONFIG = {
       'theme':'advanced',
       'width':800,
       'height':500,
   }

      from tinymce.models import HTMLField
      class Text(models.Model):
          content = HTMLField()

2. admin.py中:

# Register your models here.
from .models import Text
admin.site.register(Text)

  1. 生成数据表(python manage.py migrate)
  2. 创建admin管理用户(python manage.py createsuperuser)
    在自定义视图中使用:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>富文本</title>
    <script type="text/javascript" src="/static/tiny_mce/tiny_mce.js"></script>
    <script type="text/javascript">
    tinyMCE.init({
    {# # 给什么标签加#}
    'mode':'textareas',
    'theme':'advanced',
    'width':800,
    'height':500,
    })
    </script>
    </head>
    <body>
    <textarea></textarea>
    </body>
    </html>

    celery
    文档:http://docs.jinkan.org/docs/celery/
  3. 问题:用户发起request,并等待response返回。在当前views中,可能需要较长时间,那么用户就会等着,造成不良好体验;网站每隔一段时间需要同步一些数据,但是http请求是需要发出的,难道需要每隔一段时间就请求一次吗?
  4. 解决:使用celery,将耗时操作交给celery去执行;使用celery定时操作
  5. celery:
    任务:task, 就是一个Python函数,一个耗时操作就是一个任务
    队列:queue, 将需要执行的任务加入到队列中
    工人:worker, 在一个新的进程中,负责执行队列中的任务
    代理:broker, 负责调度,在布置环境中使用redis
  6. 安装
    pip install celery
    pip install celery-with-redis
    pip install django-celery
  7. 配置settings.py:

      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles',
          'myApp',
          'tinymce',
          'djcelery',
      ]
    
      # celery配置
      import djcelery
      djcelery.setup_loader()
      BROKER_URL = 'redis://用户名@127.0.0.1'
      CELERY_IMPORTS = ('myApp.task')
    
  8. 在项目目录下创建task.py文件

      from celery import task
      import time
    
      @task
      def longIO():
          print('111111111111111')
          time.sleep(5)
          print('2222222222')
    
  9. 迁移,生成celery数据表(python manage.py migrate)
  10. 在工程目录下的project目录下的init.py中增加

      from .celery import app as celery_app
    
  11. 在工程目录下的project目录下创建名为celery.py的文件

      from __future__ import absolute_import
      import os
      from celery import Celery
      from django.conf  import settings
    
      os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'whthas_home.settings')
    
      app = Celery('portal')
    
      app.config_from_object('django.conf:settings')
      app.autodiscover_tasks(lambda :settings.INSTALLED_APPS)
    
      @app.task(bin=True)
      def debug_task(self):
          print('Request:{0!r}'.format(self.request))
    
  12. 启动redis
  13. 启动worker:python manage.py celery worker –loglevel=info
    from .task import longIO
    def celery(request):
    longIO.delay()
    return HttpResponse('响应')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值