美文网首页我爱编程
(六) Django其他操作

(六) Django其他操作

作者: fanhang64 | 来源:发表于2018-03-21 11:55 被阅读39次

    一. 静态文件

    管理静态文件(例如:图片, js, css, 字体)

    概念: 网站通常需要提供其他的文件, 如:图片,js等, 我们将这些文件称之为静态文件

    配置静态文件:

    (1) 在settings.py中 找到INSTALLED_APPS
    INSTALLED_APPS = [
        ..
        'django.contrib.staticfiles',  # 默认添加好了
    ]
    
    (2) 在settings.py中, 最后, 添加STATICFILES_DIRS
    STATIC_URL = '/static/'
    STATICFILES_DIRS = [              # 新添加
        os.path.join(BASE_DIR,'static')
    ]
    
    (3) 在当前项目文件夹(project)中创建同级的文件夹(static)
    project
    |-myApp
    |-project
    |-static
    |-templates
    |-manage.py
    
    (4) 在模板中使用静态文件
    {% load static from staticfiles%}
    <link rel="stylesheet" href="/static/myApp/css/index.css">   # 不建议
    <link rel="stylesheet" href="{% static 'myApp/css/index.css' %}">  # 建议使用
    <img src="/static/myApp/img/1.jpg" alt="" width="300" height="100">
    

    二. 文件上传

    概述: 文件上传到服务器端, 文件存储在表单里, 使用request.FILES去接收

    注意:

    1. form表单需要设置表单为post
    2. 修改form表单的enctype的值

    存储路径:

    1. 在static下创建upfile目录, 作为文件上传的目录

    2. 在settings.py文件下添加如下代码(文件存储路径)

      MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upfile')
      

    文件上传的常用属性和方法:

    myFile = request.FILES.get('file')

    属性:

    1. myFile.name # 获取当前文件上传的文件名称(可以获取后缀)
    2. myFile.size # 获取当前文件上传的大小

    方法:

    1. myFile.read() # 从文件读取整个上传的数据(只适用于小文件)
    2. myFile.chunks() # 按块返回文件, 在for循环中, 可以将大的上传文件按块写入到服务器中
    3. myFile.multiple_chunks() # 按照文件的大小会返回True和False(当文件大于2.5Mb时返回True), 可以根据该方法判断是使用read()还是chunks()

    文件上传实例:

    index.html

    <form action="{% url 'myApp:upload' %}" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <p><input type="file" name="file"></p>
        <p><input type="submit" value="提交"></p>
    </form>
    

    views.py

    from django.conf import settings
    import os
    # 处理文件上传的视图
    def doUpload(request):
        myFile = request.FILES.get('file')
        print(myFile)
        print(myFile.name)  # 获取图片名称
        print(myFile.size)  # 获取图片大小
        print(myFile.multiple_chunks())  # 判断文件大小是否大于2.5,大于返回True
        # 拼凑完整上传的路径
        filepath = os.path.join(settings.MEDIA_ROOT, myFile.name)
        with open(filepath, 'wb') as f:
            if myFile.multiple_chunks():  # 大于2.5Mb
                for file in myFile.chunks():  # 循环按块读写
                    f.write(file)
            else:
                f.write(myFile.read())
        return HttpResponse('文件上传成功 名称为 %s 大小为 %d'%(myFile.name, myFile.size))
    

    三. 分页

    (1) Paginator对象

    导入:

    from django.core.paginator import Paginator
    
    1. 创建对象

    格式: Paginator(列表, 整数) # 列表从数据库中查出来的all()的数据, 整数是每页显示的条数

    返回值; 返回分页的对象

    2. 属性

    count # 对象的总数

    num_pages # 当前页面的总数(最大值)

    page_range # 返回页码的列表[1,2,3,4,5]

    3. 方法

    page(num) # 获取Page对象, 如果当前页码不存在, 则抛出异常

    4. 异常
    • EmptyPage # 当向page传递一个值, 但是该页面没有数据的显示, 则抛出
    • InvalidPage # 当页码不存在(无效的页码)则抛出
    • PageNotAnInteger # 当向Page() 传递一个非整数的值, 则抛出

    (2) Page对象

    1. 创建对象

    Paginator对象的Page方法返回Page对象, 不需要手动创建

    2. 属性
    • object_list # 当前页面上所有的数据,返回查询集
    • number # 当前的页码值
    3. 方法
    • has_next() # 判断是否有下一页, 如果有返回True
    • has_previous() # 判断是否有上一页, 如果有返回True
    • has_other_pages() # 判断是否有上一页或下一页, 如果有返回True
    • next_page_number() # 返回下一页的页码, 如果不存在, 则抛出InvalidPage异常
    • previous_page_number() # 返回上一页的页码, 如果不存在, 则抛出InvalidPage异常
    • len() # 返回当前页的数据个数

    实例:

    pageShow.html

    <ol>
        {% for s in page %}
        <li>{{ s.sname }}</li>
        {% endfor %}
    </ol>
    <p>
        {% for p in page.paginator.page_range %}
            {% if p == page.number %}  # 判断如果为当前页面,只显示数字(没有链接)
                {{ p }}
            {% else %}
                <a href="{% url 'myApp:pageShow' p %}">{{ p }}</a>
            {% endif %}
        {% endfor %}
    </p>
    

    urls.py

     url(r'^pageShow/(\d+)/', views.pageShow, name='pageShow'),
    

    views.py

    # 分页处理的视图
    def pageShow(request, nowPage):
        allStu = Students.stuObj.all()
        everyPage = 2
        pag = Paginator(allStu, everyPage)  # 参数(要分页的列表数据, 每页显示的条数)
        print(pag.num_pages)  # 输出当前页面的总数
        # nowPage = 1  # 当前页码
        print(pag.page(nowPage))  # <Page 1 of 3> 输出page对象
        try:
            page = pag.page(nowPage)
        except:
            page = pag.page(pag.num_pages)  # 如果存在异常, 使用当前页面的最大值
        return render(request, 'myApp/pageshow.html', {'page': page})
    

    四. ajax请求

    格式:

    $.get(URL,callback);
    $.post(URL,data,callback);
    

    模板

    $(function () {
       $('button').click(function () {
       $.get('{% url 'myApp:ajaxRequest'%}', function (data, status) {
          console.log(data);
          console.log(status);
          // a = JSON.parse(data);  如果视图函数使用json.dumps(),需要使用此函数解析
          // console.log(a);
          // for (var i in data) {
          //    console.log(i); // 未解析,显示data
          // }
          myStr = '';
          for (var i in data.data) {  // i代表输出索引值
                myStr += '<li>'+data.data[i][0]+','+data.data[i][1]+'</li>';
                $('ul').append(myStr)
          }
      })
     })
    })
    <ul>
        <p><button>点击请求ajax</button></p>
    </ul>
    

    视图

    def ajaxRequest(requst):   # 给ajax返回请求数据
        if requst.is_ajax():  # 判断是否为ajax请求
            stu = Students.stuObj.all()
            l = []
            for i in stu:
                l.append([i.sname, i.ssex])
            # return JsonResponse({'data': ['zs', 18]})
            # return JsonResponse({'data': l})  # l为二维列表, 使用JsonResponse在js里不需要解析
            return HttpResponse(json.dumps({'data': l}))  # 字符串,在js里需要使用JSON.parse()解析, 解析以后和JsonResponse一样
        else:
            return JsonResponse({'data': ['error']})
    

    五. 富文本编辑器

    安装:

    pip install django-tinymce

    (1) 配置settings.py文件

    在INSTALLED_APP中添加tinymce, 同时添加

    TINYMCE_DAFAULT_CONFIG = {
        'theme':'advanced',
        'width':600,
        'height':400
    }
    
    (2) 创建模型类(在models.py文件中)
    from tinymce.models import HTMLField
    class Text(models.Model):
        myStr = HTMLField()
    
    (3) 进行文件迁移

    删除库重新生成数据库

    (4) 配置站点

    在admin.py中添加

    from myApp.models import Text
    admin.site.register(Text)
    
    (5) 在模板中使用
    # 添加js
    <scipt src='{% static 'tiny_mce/tiny_mce.js'%}'></script>  # 注意不加static
    <script>
    tinyMCE.init({
        'mode':'textareas',
        'them':'advanced',
        'width':800,
        'height':600
    })
    </script>
    <textarea name="str"></textarea>
    

    注意: /static/tiny_mce/tiny_mce.js文件夹和文件是隐藏的

    六. celery

    视图处理比较耗时的代码, 会降低用户的体验度, 也就是说需要用户请求完以后, 有时间的等待, 然后才能响应给用户.

    (1) celery

    1. 任务

    将耗时的代码封装成一个函数

    2. 队列

    将要执行的任务放到队列里

    3. 工人

    负责执行队列中的任务

    4. 代理

    负责当前的调度, 在部署环境中使用redis

    (2) 安装模块

    pip install celery

    pip install celery-with-redis

    pip install django-celery

    (3) 配置settings.py文件

    找到INSTALLED_APPS添加如下代码

    'djcelery',
    

    在settings.py下方添加代码(配置redis)

    import djcelery
    djcelery.setup_loader()  # 初始化
    BROKER_URL = 'redis://:密码@127.0.0.1:6379/0'  # 配置连接数据库, 选择0数据库
    CELERY_IMPORTS = ('myApp.task')  # myApp为当前应用名称
    

    (4) 生成celery所需要的表(不需要生成迁移文件,没有修改model)

    python manage.py migrate

    (5) 配置celery

    在当前工程目录project下的同名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(bind=True)
    def debug_task(self):
        print('Request: {0!r}'.format(self.request))
    

    (6) 在工程目录__init__.py下添加

    from .celery import app as celery_app
    

    (7) 在myApp下创建(task.py)延时任务的代码段

    from celery.task import task
    import time
    @task
    def tt():
        print('开始执行延时任务')
        time.sleep(5)
        print('执行延时任务结束')
    

    (8) 在对应的视图中, 使用耗时的代码段(函数)

    from .tast import tt
    def index(request):
        tt.delay()
        return render(request, 'myApp/index.html')
    

    (9) 启动redis

    ->redis-server.exe redis-windows-conf
    # 打开新终端
    ->redis-cli
    ->auth 123  # 密码
    

    10) 启动服务

    python manage.py runserver 0.0.0:8000
    

    (11) 启动worker

    cd 当前项目目录下
    python manage.py celery worker --loglevel=info
    

    七. 中间件

    概述: 轻量级底层的插件

    作用: 加入django的请求和响应之间

    本质: 一个python类

    1. 方法
    • init() # 不需要传参, 作为初始化

    • process_request(self, request) # 在执行视图之前被调用(分配url匹配视图之前)返回None或者HttpResponse对象

    • process_view(self, request,view_func, view_args, view_kwargs) # 调用视图之前被执行

    • process_template_response(self, request, response) # 在视图刚好执行完后去调用, 返回None或者HttpResponse对象

    • process_exception(self, request, exception) # 当视图抛出异常的时候调用, 返回HttpResponse对象

    自定义中间件

    1. 在project项目目录下(与myApp同级的)去创建middleware目录, 在目录里创建myApp目录

    2. 在middleware中的myApp目录下创建myMiddle.py文件

      from django.utils.deprecation import MiddlewareMiXin
      
      class MyMiddle(MiddlewareMiXin):
          def process_request(self, request):
              print('get传参的参数为',request.GET.get('state'))
      
    3. 在settings.py文件中

      MIDDLEWARE = [
        ..
        'middleware.myApp.myMiddle.MyMiddle'
      ]
      
    4. 在浏览器填写地址

      localhost:8000/?state=100
      

    相关文章

      网友评论

        本文标题:(六) Django其他操作

        本文链接:https://www.haomeiwen.com/subject/uzgwqftx.html