zoukankan      html  css  js  c++  java
  • django——文件上传_分页_ajax_富文本_celery

    上传文件

    概述

    当Django在处理文件上传时,文件的数据被存储在request.FILES属性中

    FILES只有在请求的方法为POST且提交的form表单带有enctype="multipart/form-data"属性的情况才会包含数据。否则,FILES将为一个空的类似字典的对象

    FILES中的键为input的name属性值

    上传界面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>文件上传</title>
    </head>
    <body>
        <form method="post" action="/upfile/" enctype="multipart/form-data">
            {% csrf_token %}
            <input type="file" name="file">
            <input type="file" name="file">
            <input type="file" name="pic">
            <input type="submit" value="上传">
        </form>
    </body>
    </html>

    文件存储路径

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

    配置路径:

    settings

    # 文件上传的路径
    MEDIA_URL = '/media/'   # 访问资源的地址如 http://127.0.0.1:5000/media/1.jpg
    # 写相对路径也可以
    MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")

    request.FILES数据结构

    {
        'file': [
            <InMemoryUploadedFile: a.txt (text/plain)>, 
            <InMemoryUploadedFile: b.txt (text/plain)>
        ], 
        'pic': [
            <InMemoryUploadedFile: c.jpg (image/jpeg)>
        ]
    }

    视图实现

    from django.conf import settings
    def upfile(request):
        if request.method == "GET":
            return render(request, "upfile.html")
        else:
            # print(request.FILES)
            for name in request.FILES:
                files = request.FILES.getlist(name)
                # print(files)
                for file in files:
                    #处理每个文件
                    filePath = r"%s\%s"%(settings.MEDIA_ROOT,file.name)
                    with open(filePath, "wb") as fp:
                        # 将文件数据切片写入描述符
                        for part in file.chunks():
                            fp.write(part)
            return HttpResponse("上传文件成功")

    图片生成缩略图

    # 生成缩略图
    
    from PIL import Image
    im = Image.open('c.jpg')
    print(im.format, im.size, im.mode)
    # JPEG (840, 1024) RGB
    im.thumbnail((100,200))
    im.save("c1.jpg", "JPEG")

    分页

    Paginator对象

    Page对象

    示例

    from django.core.paginator import Paginator
    def students(request, num):
        allStudents = Student.objects.all()
        #分页 每页6条数据
        paginator = Paginator(allStudents, 6)
        print(paginator.count, paginator.num_pages, paginator.page_range)
        pageStus = paginator.page(num)
        return render(request, "students.html", {"stus":pageStus})
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>学生信息</title>
    </head>
    <body>
    <h1>学生信息</h1>
    <ul>
        {% for stu in stus %}
            <li>{{ stu.name }}--{{ stu.grade }}--{{ stu.age }}</li>
        {% endfor %}
    </ul>
    {% if stus.has_previous %}
        <a href="/students/{{ stus.previous_page_number }}">上一页</a>
    {% 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.next_page_number }}">下一页</a>
    {% endif %}
    </body>
    </html>

    Ajax

    问题

    使用视图通过上下文向模板中传递数据,需要先加载完成模板的静态页面,再执行模板模型代码,生成最后的HTML代码,返回给浏览器,这个过程将页面与数据集成到了一起,扩展性差

    解决

    通过ajax的方式获取数据,再通过DOM操作将数据呈现到界面上

    异步:如发邮件(注册的时候提示邮件已经发送成功,其实并没有) 能提高用户体验。 如豆瓣,防止页面卡死。

    前端代码

    <!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>
        <ul id="stus">
    
        </ul>
    
        <script type="text/javascript">
            $(document).ready(function () {
                $("#btn").bind("click", function () {
                    /*
                    $.get("/allStudents/",{"a":1,"b":2},function (data, status) {
                        console.log("************************2");
                        console.log(data, status);
                        stus = data["data"];
                        for (var i = 0; i < stus.length; i++){
                            stu = stus[i];
                            $li = $("<li>"+stu.name+"---"+stu.age+"</li>");
                            $("#stus").append($li)
                        }
                    });
                    */
                    $.ajax({
                        url:"/allStudents/",
                        type:"get",
                        data:{"a":1,"b":2,"c":3},
                        dataType:"json",
                        success:function (data, status) {
                            console.log("************************2");
                            console.log(data, status);
                            stus = data["data"];
                            for (var i = 0; i < stus.length; i++){
                                stu = stus[i];
                                $li = $("<li>"+stu.name+"&&&"+stu.age+"</li>");
                                $("#stus").append($li)
                            }
                        }
                    });
                    console.log("************************1");
                });
            });
        </script>
    </body>
    </html>
    def allStudents(request):
        if request.method == "GET":
            if not request.is_ajax():
                return render(request, "allStudents.html")
            else:
                stus = Student.objects.all()
                arr = []
                for stu in stus:
                    arr.append({"name":stu.name, "age":stu.age})
                return JsonResponse({"data":arr})

    富文本

    安装:pip install django-tinymce

    在站点中使用

    激活应用

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'myApp',
        'tinymce',
    ]

    配置

    TINYMCE_DEFAULT_CONFIG={
        'theme':'advanced',
        'width':600,
        'height':400
    }

    模型

    from tinymce.models import HTMLField
    class Article(models.Model):
        title = models.CharField(max_length=20)
        content = HTMLField()

    admin.py

    admin.site.register(Article)

    在自定义页面中使用

    <!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':600,
                'height':400
            });
        </script>
    </head>
    
    <body>
        <form method="post" action="/tinymce/">
            {% csrf_token %}
            <input type="text" name="title" value=""><hr/>
            <textarea name="article"></textarea><hr/>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

    Celery

    问题

    用户发起request请求,并等待response返回。在本次views中,可能需要执行一段耗时的程序,那么用户会等待很长时间,造成不好的用户体验

    网站每小时需要同步数据(天气预报信息),但是http是需要触发的,难道要一个小时请求一次吗?

    解决方案

    使用celery:将耗时的程序放到celery中执行 使用celery定时执行

    celery

    任务task:就是一个python函数

    队列queue:将需要执行的任务加入队列中

    工人worker:在一个新的进程中负责执行队列中的任务

    代理broker:负责调度,在布置环境中使用redis

    安装

    pip  install  celery==3.1.25
    pip  install  celery-with-redis==3.0
    pip  install  django-celery==3.2.1

    配置

    激活应用

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'myApp',
        'tinymce',
        'djcelery',
    ]

    配置redis

    #celery
    import djcelery
    djcelery.setup_loader()
    #配置redis数据库
    #redis://:密码@ip:端口/库
    BROKER_URL='redis://:sunck@127.0.0.1:6379/0'
    #配置任务文件
    CELERY_IMPORTS=("myApp.task")

    创建任务文件,并分装任务

    # 在应用目录下创建名为task.py的文件
    # -*- coding:utf-8 -*-
    from celery import task
    import time
    
    @task
    def longIO():
        print("开始耗时操作……")
        time.sleep(5)
        print("结束耗时操作……")

    迁移

    python manage.py migrate

    生成celery所需要的表

    添加celery.py文件

    将已存在的celery.py添加到工程目录下的与工程目录同名的目录下

    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))

    导入celery

    在工程目录下的与工程目录同名的目录中的__init__.py文件中添加from .celery import app as celery_app

    在视图使用任务

    from myApp.task import longIO
    def registe(request):
        longIO.delay()
        return HttpResponse("sunck is a good man")

    启动redis

    redis-server.exe redis.windows.conf

    启动worker

    python manage.py celery worker --loglevel=info

    启动Django服务

     python manage.py runserver
     
  • 相关阅读:
    09暑假总结
    给我同学的一点建议
    委托(一个主窗体统计多个从窗体的按钮单击的次数)
    关于C#写的记事本中一个问题
    IT行业最重要的四件宝我的实习体会
    使用结构、数组、循环和DataGridView写的分数统计小程序
    Visual Studio 2005 打不开,一直停在启动画面问题
    解决Cannot open the disk 'F:/vmware/Ubuntu.vmdk' or one of the snapshot disks it depends on.
    设计原则笔记
    交叉表组件
  • 原文地址:https://www.cnblogs.com/276815076/p/9406407.html
Copyright © 2011-2022 走看看