Django - 05-Django高级

[toc]

1 静态文件

定义:
        css、js、图片、json文件、字体文件等

存储位置:
        project/static/项目名/{css,js,img,json,font,other}
        
配置settings.py
        STATIC_URL = '/static/'
        STATICFILES_DIRS = [
            os.path.join(BASE_DIR, 'static'),
        ]
        
栗子:
        目录结构:
            Project
             └─static
                └─myApp
                   ├─css
                   ├─font
                   ├─img
                   ├─js
                   ├─json
                   └─other
        index.html
                <head>
                    <meta charset="UTF-8">
                    <title>index</title>
                    <link rel="stylesheet" type="text/css" href="/static/myApp/css/style.css">
                </head>
                    <script type="text/javascript" src="/static/myApp/js/lance.js"></script>
                <body>
                    <h1>lance is a good man</h1>
                    <img src="/static/myApp/img/a.png" alt="">
                </body>
                
        style.css
                h1{color: red;}
        
        lance.js
                console.log('good man')
                

普通文件动态加载static目录:(有错误 先别用)
        index.html
                {% load static from staticfiles %}
                <!DOCTYPE html>
                ...
                <img src="{% static 'myApp/img/a.png' %}" alt="">
                
        注意:
                这时的文件的链接路径 已经不需要从static开始去写了;
                settings.py中的 STATICFILES_DIRS 配置项已经无效;
                
                

2 中间件

2.1 概述

一个轻量级、底层的插件,可以介入Django的请求响应;

2.2 方法

__init__
        不需要传参数,服务器响应第一个请求的时候调用;用于确定是否启用该中间件;

process_request(self, request)
        在分配url匹配视图之前,每个请求上都会调用;返回 None 或者 HttpResponse 对象;

process_view(self, request, view_func, views_args, view_kwargs)
        调用视图之前执行,每个请求都会调用;返回 None 或者 HttpResponse 对象;

process_template(self, request, response)
        在视图执行完成后调用,每个请求都会调用;返回 None 或者 HttpResponse 对象;
        使用 render()
        
process_response(self, request, response)
        在执行模板之后调用,每个请求都会调用;返回 HttpResponse 对象;

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

2.3 自定义中间件

目录结构:
        project/middleware/myApp/
        
创建中间件:
        myMiddler.py
                from django.utils.deprecation import MiddlewareMixin
                class MyMiddler(MiddlewareMixin):
                    def process_request(self, request):
                        print("GET参数为:", request.GET.get("a"))

使用中间件:
        配置settings.py,在 MIDDLEWARE 中添加:
                'middleware.myApp.myMiddleware.MyMiddle',

验证:
        刷新界面,可以看到后台,有打印信息;

3 上传图片

3.1 概述

文件上传时,文件数据存储在request.FILES属性中;

注意:
        form表单要上传文件需要加 enctype="multipart/form-data" ;
        上传文件必须是POST请求;

3.2 存储配置

存储路径
        project/static/upfile

配置 settings.py:
        MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upfile')

3.3 示例

upfile.html
        <form action="/savefile/" method="post" enctype="multipart/form-data">
            {% csrf_token %}
            <input type="file" name="file">
            <input type="submit" value="上传">
        </form>
        
views.py
        def upfile(request):
            return render(request, 'myApp/upfile.html')
        
        import os
        from django.conf import settings
        def savefile(request):
            if request.method == "POST":
                f = request.FILES["file"]
                # 文件在服务器端的路径
                filePath = os.path.join(settings.MEDIA_ROOT, f.name)
                with open(filePath, 'wb') as fp:
                    for info in f.chunks():     # 分段读取文件内容
                        fp.write(info)
                        fp.flush()
                return HttpResponse('上传成功')
            else:
                return HttpResponse("上传失败")
                
urls.py
        url(r'^upfile/$', views.upfile),
        url(r'^savefile/$', views.savefile),

4 分页

from django.core.paginator import Paginator

4.1 Paginator对象

创建对象
        格式:
                Paginator(列表, 整数)       # (所有的数据,每页几个)
        
        返回值:
                返回分页对象

属性
        count       对象总数
        
        num_pages   页面总数
        
        page_range  
                页码列表
                [1,2,3,4,5]
                页码从1开始

方法
        page(num)
                获得一个Page对象,如果提供的页码不存在,会抛出一个 'InvalidPage' 异常

异常
        InvalidPage
                当向 page() 传递一个无效的页码时抛出;
                
        PageNotAnInteger
                当向 page() 传递一个不是整数的参数时抛出;

        EmptyPage
                当向 page() 传递一个有效,但是该页面没有数据时抛出;

4.2 Page对象

创建对象
        Paginator对象的page方法返回得到Pafe对象;
        不需要手动创建;

属性
        object_list
                当前页上的所有的数据(对象)列表;
                
        number
                当前页的页码值;
        
        paginator
                当前page对象关联的paginator对象;
                
方法
        has_next()
                判断是否有下一页,如果有返回True;
                
        has_previous()
                判断是否有上一页,如果有返回True;
                
        has_other_pages()
                判断是否有上一页或者下一页,如果有返回True;
                
        next_page_number()
                返回下一页的页码,如故下一页不存在,抛出InvalidPage异常;
                
        previous_page_number()
                返回上一页的页码,如故上一页不存在,抛出InvalidPage异常;
                
        len()
                返回当前页的数据个数;

4.3 Paginator对象与Page对象的关系

Paginator对象 把 Student.object.all() 返回的列表分割;
使用 Paginator对象的 page方法,生成对应列表段的 Page对象;
每个Page对象,对应列表段中的内容;

4.4 示例:分页显示学生信息

studentpage.html
    <ul><li>{{ pagenum }}</li></ul>
    <ul>
        {% for stu in student %}
            <li>{{ stu.id }} | {{ stu.sname }} | {{ stu.sgrade }}</li>
        {% endfor %}
    </ul>
    <ul>
        {% for index in student.paginator.page_range %}
        {# 调用page对象的paginator方法,到达paginator类;#}
        {# 再使用paginator类的page_range方法;#}
            <li><a href="/studentpage/{{ index }}/">{{ index }}</a></li>
        {% endfor %}
    </ul>
    
views.py
        from django.core.paginator import Paginator
        def studentpage(request, pageid):
            # 所有学生的列表
            allList = Student.stuObj.all()
            paginator = Paginator(allList, 3)
            page = paginator.page(pageid)
            pagenum = page.number
            return render(request, 'myapp/studentpage.html', {"student": page, "pagenum": pagenum})

urls.py
        url(r'^studentpage/(\d+)/$', views.studentpage),

5 ajax

需要动态生成,请求json数据

栗子:
        views.py
                from django.http import JsonResponse
                def ajaxstudet(request):
                    stus = Student.stuObj.all()
                    list = []
                    for stu in stus:
                        list.append([stu.id, stu.sname, stu.sgrade])
                    return JsonResponse({"data": list})

6 富文本

pip install django-tinymce

在站点中使用
        配置settings.py文件
                在INSTALLED_APPS中添加:'tinymce',
                在末尾追加:
                        # 富文本
                        TINYMCE_DEFAULT_CONFIG = {
                            'theme': 'advanced',
                            'width': 600,
                            'height': 400,
                        }
                        
        创建一个模型类(myApp/models.py):
                from tinymce.models import HTMLField
                class Text(models.Model):
                    str = HTMLField()
                    
        配置站点(myApp/admin.py):
                from .models import Text
                admin.site.register(Text)
                

在自定义视图中使用
        urls.py
                url(r'^edit/$', views.edit),
                
        views.py
                def edit(request):
                    return render(request, 'myApp/edit.html')
                    
        edit.html
                <!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 action="">
                    <textarea name="str">lance is good man</textarea>
                    <input type="submit" value="提交">
                </form>
                </body>
                </html>

7 celery

http://docs.jinkan.org/docs/celery/

问题:
        1. 用户发起request,并且要等待response返回;但是在视图中有一些耗时的操作,导致用户可能会等待很长时间才能接受response,这样用户体验很差;
        
        2. 网站每隔一段时间要同步数据,但是http请求是需要触发的;


celery解决:
        问题1: 将耗时的操作,放到celery中执行;
        问题2: 使用celery定时执行;


celery组件:
        任务tasl        本质是一个Python函数,将耗时操作封装成一个函数;
        队列queue       将要执行的任务,放到队列里;
        工人woeker      负责执行队列中的任务;
        代理broker       负责调度,在部署环境中使用redies;


安装:
        pip install celery
        pip install celery-with-redis
        pip install django-celery
       
        
配置settings.py:
        INSTALLED_APPS
                'djcelery',
                
        追加
                import djcelery
                djcelery.setup_loader()     #初始化
                BROKER_URL = 'redis://:user@IP:6379/0'
                CELERY_IMPORTS = ('myApp.task',)
            
               
创建task.py
        project/myApp/task.py


迁移,生成celery需要的数据库表:
        python manage.py migrate


在 /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_MODULES', 'whthas_home.settings')
        app = Celery('portal')
        
        app.config_from_onject('django.conf:settings')
        app.authodiscover_tasks(lambda: settings.INSTALLED_APPS)
        
        @app.task(bind=True)
        def debug_task(self):
        print('Request: {0!r}'.format(self.request))


在project/project/__init__.py中添加:
    from .celery import import app as celery_app
    









©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354