2020-06-22(2)

2020-06-22  本文已影响0人  python小哥哥2020

****************************************第二篇笔记从这里开始************************************************


模板
    定义模板
        变量
            变量传递给模板的数据
            要遵守标识符规则
            语法 {{ var }}
            注意:如果使用的变量不存在,则插入的是空字符串
            在模板中使用点语法
                字典查询
                属性或者方法
                数字索引
            在模板中调用对象的方法
                注意:在模板里定义的函数不能传递self以外的参数
        标签:语法   {% tag %}
            作用
                在输出中创建文本
                控制逻辑和循环
        标签示例:    
            if 格式 
                    {% if 表达式 %}
                        语句
                    {% endif %}
            if-else 格式   
                        {% if 表达式 %}
                            语句1
                        {% else %}
                            语句else
                        {% endif %}
            if-elif-else 格式 
                        {% if 表达式 %}
                            语句1
                        {% elif 表达式 %}
                            语句2
                        ...

                        {% else %}
                            语句else
                        {% endif %}
            for 格式
                    {% for 变量 in 列表 %}
                        语句
                    {% endfor %}
                格式2
                    {% for 变量 in 列表 %}
                        语句
                    {% empty %}  # 注意:列表为空或者列表不存在时执行语句2
                        语句2
                    {% endfor %}
                格式3
                    {{ forloop.counter }}
                示例:
                    <ul>
                        {% for stu in students %}
                            <li>
                                {{forloop.counter}}--{{stu.sname}}--{{stu.sgrade}}
                            </li>
                        {% empty %}
                            <li>目前没有学生</li>
                        {% endfor %}
            commnet 格式
                {% commnet %}
                    被注释的内容
                {% endcomment %}
                作用:相当于多行注释,被注释的内容不再执行
            ifequal/ifnotequal 作用 判断是否相等或者不相等
                格式
                    {% ifequal 值1 值2 %}
                        语句1
                    {% endifequal %}  # 如果值1等于值2,执行语句1,否则不执行语句1
            include
                作用:加载模板并以标签内的参数渲染
                格式:{% include '模板目录' 参数1 参数2 %}
            url
                作用:反射解析
                格式:{% url 'namespace: name' p1 p2 %}
            csrf_token
                作用:用于跨站请求伪造保护
                格式:{% csrf_token %}
            block, extends
                作用:用于模板的继承
            autoescape
                作用:用于HTML转义
        过滤器
            语法 {{ var|过滤器 }}
            作用:在变量被显示前修改它,只是加一个效果,对变量不会造成影响
            示例:
                lower
                upper
            过滤器可以传递参数,参数用引号引起来
                join 格式 列表|join:"#"
                     示例:{{list1|join:"#"}}
            如果一个变量没有被提供,或者值为false,空,我们可以通过 default 语法使用默认值
                格式: {{str1|default:"没有"}}
            根据给定格式转换日期为字符串:date
                格式: {{dateVal|date:'y-m-d'}}
            HTML转义:escape
            加减乘除示例:
                <h1>num = {{num|add:10}}</h1>
                <h1>num = {{num|add:-10}}</h1>
                <h1>num = {% num widthratio num 1 5%}</h1>
                <h1>num = {% num widthratio num 5 1%}</h1>
        注释
            单行注释:语法: {# 被注释的内容 #}
            多行注释
                {% commnet %}
                    被注释的内容
                {% endcomment %}

    反射解析
        示例:
            project/project/urls.py
            url(r'^', include('myApp.urls', namespace='app')),
            project/myApp/urls.py
            url(r'^good/(\d+)$', views.good, name="good")
            templates/good.html
            <a href={% url 'app:good' 1 %}>链接</a>

    模板继承
        作用:模板继承可以减少页面的重复定义,实现页面的重用
        block标签:在父模板中预留区域 ,子模板去填充
            语法 : {% block 标签名 %}

                    {% endblock 标签名 %}
        extends标签:继承模板,需要写在模板文件的第一行
            语法 : {% extends 'myApp/base.html' %}
                    {% block main %}
                        内容
                    {% endblock 标签名 %}
        示例:
            定义父模板
                body标签中
                {% block main %}
                        
                {% endblock main %}

                {% block main %}
                        
                {% endblock main2 %}
            定义子模板
                {% extends 'myApp/base.html' %}
                {% block main %}
                    <h1>sunck is a good man</h1>
                {% endblock main %}

                {% block main2 %}
                    <h1>kaige is a good man</h1>
                {% endblock main2 %}

    HTML转义
        问题:return render(request, 'myApp/index.html', {"code": "<h1>sunck is a very good man</h1>"})中的{{code}}
              {{code}}里的code被当作<h1>sunck is a very good man</h1>显示,未经过渲染
        解决方法:
            {{code|safe}}
        或  {% autoescape off %}
                {{code}}
            {% endautoescape %}  # 这个可以一口气解决一堆

    CSRF:
    跨站请求伪造
        某些恶意网站包含链接,表单,按钮,js,利用登录用户在浏览器中认证,从而攻击服务
    防止CSRF
        在settings.py文件的MIDDLEWARE增加'django.middleware.csrf.CsrfViewMiddleware'
        {% csrf_token %}        

    验证码
        作用
            在用户注册,登录页面的时候使用,为了防止暴力请求,减轻服务器的压力
            是防止CSRF的一种方式

    验证码代码示例:
写在views.py里面
=================================================================================================
def verifycode(request):
    # 引入绘图模块
    from PIL import Image, ImageDraw, ImageFont
    # 引入随机函数模块
    import random
    # 定义变量,用于画面的背景色,宽,高
    bgcolor = (random.randrange(20, 100), random.randrange(20, 100), random.randrange(20, 100))
    width = 100
    height = 50
    # 创建画面对象
    im = Image.new('RGB', (width, height), bgcolor)
    # 创建画面对象
    draw = ImageDraw.Draw(im)
    # 调用画笔的point()函数绘制噪点
    for i in range(0, 100):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
        draw.point(xy, fill=fill)
    # 定义验证码的备选值
    str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
    # 随机选取4个值作为验证码
    rand_str = ''
    for i in range(0, 4):
        rand_str += str[random.randrange(0, len(str))]
    # 构造字体对象
    font = ImageFont.truetype(r'C:\Windows\Fonts\AdobeArabic-Bold.otf', 40)
    # 构造字体颜色
    fontcolor1 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor2 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor3 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor4 = (255, random.randrange(0, 255), random.randrange(0, 255))
    # 绘制4个字
    draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1)
    draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2)
    draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3)
    draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4)
    # 释放画笔 
    del draw
    # 存入session,用于做进一步的验证
    request.session['verifycode'] = rand_str
    # 内存文件操作
    import io
    buf = io.BytesIO()
    # 将图片保存在内存中,文件类型为png
    im.save(buf, 'png')
    # 将内存中的图片数据返回给客户端,MIME类型为图片png
    return HttpResponse(buf.getvalue(), 'image/png')


from django.shortcuts import render, redirect
def verifycodefile(request):
    f = request.session["falg"]
    str = ""
    if f == False:
        str = "请重新输入!"
    request.session.clear()
    return render(request, 'myApp/verifycodefile.html', {"flag":str})

def verifycodecheck(request):
    code1 = request.POST.get("verifycode").upper()
    code2 = request.session["verify"].upper()
    if code1 == code2:
        return render(request, 'myApp/success.html')
    else:
        request.session["flag"] = False
        return redirect('/verifycodefile')

==============================================================================
写在verifycodefile.html的<body>标签中
<body>
    <form method="post" action="/verifycodecheck/">
        {%csrf_token%}
        <input type="text" name="verifycode"/>
        <img src="/verifycode">
        <input type="submit" name="登录">
        <span>{{flag}}</span>
    </form>
</body>

==============================================================================


Django高级扩展
    静态文件
        css,js,图片,json文件,字体文件等
        配置settings.py
            STATIC_URL = '/static'
            STATICFILES_DIRS = [
                os.path.join(BASE_DIR, 'static')
            ]

    中间件
        概述:一个轻量级,底层的插件,可以介入Django的请求和响应。
        本质:一个Python类
        方法:
            __init__ 
                不需要传参数,服务器响应第一个请求的时候自动调用,用于确定是否启用该中间件
            process_request(self, request) 
                在执行视图之前被调用(分配url匹配视图之前),每个请求都会调用,返回None或者HttpResponse对象
            process_view(self, request, view_func. view_args, view_kwargs)
                调用视图之前执行,每个请求都会调用,返回None或者HttpResponse对象
            process_template_response(self, request, response)
                在视图刚好执行完后调用,每个请求都会调用,返回None或者HttpResponse对象
                使用render
            process_response(self, request, response)
                所有响应返回浏览器之前调用,每个请求都会调用,返回HttpResponse对象
            process_exception(self, request, exception)
                当视图抛出异常时调用,返回HttpResponse对象
        执行过程:
            __init__ --> process_request--> url --> process_view --> view --> process_template_response --> template --> process_response -->返回开头部分
         执行位置:
        自定义中间件
            在工程目录下的middleware目录下创建myApp
            创建一个python文件
            from django.utils.deprecation import middlewareMixin
            class MyMiddle(middlewareMixin):
                def process_request(self, request):
                    print("get参数为: ", request.GET.get("a"))
        使用自定义中间件
            配置settings.py文件 在MIDDLEWARE中添加 'middleware.myApp.MyMiddle.MyMiddle',

    上传图片
        概述:
            文件上传时,文件数据request.FILES属性中.
            注意:form表单要上传文件需要加enctype="multipart/form-data"
            注意:上传文件必须用post请求
        存储路径:
            在static目录下创建upfile目录用于存储上传的文件
            配置settings.py文件 MDEIA_ROOT = os.path.join(BASE_DIR, r'static\upfile')

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.pasth.join(settings.MDEIA_ROOT, f.name)
        with open(filePath, 'wb') as fp:
            for info in f.chunks():
                fp.write(info)
        return HttpResponse("上传成功。")
    else:
        return HttpResponse("上传失败。")
==============================================================================
upfile.html中<body>里的内容
<body>
    <form method="post" action="/savefile" enctype="multipart/form-data">
        {%csrf_token%}
        <input type="file" name="file"/>
        <input type="submit" value="上传"/>
    </form>
</body>
==============================================================================

    分页
        Paginator对象
            创建对象
                格式 Paginator(列表,整数)
                返回值 返回的分页对象
            属性
                count 对象总数
                num_pages 页面总数
                page_range
                    页码列表
                    [1,2,3,4,5]
                    页码从1开始
            方法
                page(num) 获得一个Page对象,如果提供的页码不存在会抛出"InvalidPage"异常
            异常
                InvalidPage:当向 page()传递的是一个无效的页码时抛出
                PageNotAnInteger:当向 page()传递的不是一个整数时抛出
                EmptyPage:当向 page()传递一个有效值,但是该页面里没有数据时抛出
        Page对象
            创建对象
                Paginator对象的 page()方法返回得到Page对象
                不需要手动创建
            属性
                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() 返回当前页的数据(对象)个数

        Paginator与Page对象关系(略)
        代码示例:
        配置路由:url(r'^studentpage/(\d+)/$', views.studentpage),
        配置视图:
            from .models import Students
            from django.core.paginator import Paginator
            def studentpage(request, pageid):
                # 所有学生列表
                allList = Students.objects.all()
                paginator = Paginator(allList, 6)
                page = paginator.page(pageid)
                return render(request, 'myApp/studentpage.html', {"students": page})
        配置html
        studentpage.html中body标签中的内容:
            <body>
                <ul>
                    {% for stu in students %}
                    <li>
                        {{stu.sname}}--{{stu.sgrade}}
                    </li>
                    {% endfor %}
                </ul>
                <ul>
                    {% for index in students.paginator.page_range %}
                        {% if index == students.number %}
                            <li>
                                {{index}}
                            </li>
                        {% else %}
                            <li>
                                <a href="/sunck/studentpage/{{index}}">{{index}}</a>
                            </li>
                        {% endif %}
                    {% endif%}
                </ul>
            </body>
==============================================================================

    ajax
        需要动态生成,请求JSON数据
    代码示例
        ajaxstudents.html页面示例
        <script type="text/javascript" src="/static/myApp/js/jquery-3.1.1.min.js"></script>
        <body>
            <h1>学生信息列表</h1>
            <button id="btn">显示学生信息</button>
            <script type="text/javascript" src="/static/myApp/js/sunck.js"></script>
        </body>

        sunck.js代码示例
        $(document).ready(function (){
            document.getElementById("btn").onclick = function (){
                $.ajax({
                    type:"get",
                    url:"/studentsinfo/",
                    dataType:"json",
                    success:function(data, status){
                        console.log(data)
                        var d = data["data"]
                        for(var i=0; i<d.length; i++){
                            document.write('<p>' + d[i][0] + '</p>')
                        }
                    }
                })
            }
        })

        views.py代码示例
        def ajaxstudents(request):
            return render(request, 'myApp/ajaxstudents.html')

        from django.http import JsonResponse
        def studentsinfo(request):
            stus = Students.objects.all()
            list = []
            for stu in stus:
                list.append([stu.sname, stu.sage])
            return JsonResponse({"data":list})
==============================================================================

    富文本
        pip install django-tinymce
        在站点中使用
            配置settings.py文件
                INSTALLED_APPS 列表中添加 'tinymce',
                增加    
                    # 富文本
                    TINYMCE_DEFAULT_CONFIG = {
                        'theme':'advanced',
                        'width':600,
                        'height':400,
                    }
            创建一个模型类:
                在models.py文件中增加
                from tinymce.models import HTMLField
                class Text(models.Model):
                    str = HTMLField()
            配置站点:
                from .models import Text
                admin.site.register(Text)
        
        自定义视图使用
            <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':'600',
                        })
                </script>
            </head>
            <body>
                <form action="/saveedit/" method="post">
                    <textarea name="str">sunck is a good man</textarea>
                    <input type="submit" value="提交"/>
                </form>
            </body>

        Celery
            http://docs.jinkan.org/docs/celery/
            问题:
                用户发起request,并且要等待response返回,但在视图中有一些耗时的操作,
                导致用户可能会等待很长时间才能接收response,这样用户体验很差
                网站每隔一段时间要同步一次数据,但是http请求是需要触发的
            解决:
                celery来解决
                    将耗时的操作放在celery中执行
                    使用celery定时执行
            celery:
                任务task
                    本质是一个Python函数,将耗时的操作封装成一个函数
                队列queue
                    将要执行的任务放在队列里
                工人worker
                    负责执行对列中的任务
                代理broker
                    负责高度,在部署环境中使用redis
            安装:
                pip install celery
                pip install celery-with-redis
                pip install django-celery
            配置settings.py
                在INSTALLED_APPS 列表中添加 'djcelery',
                # Celery
                import djcelery
                djcelery.setup_loader() # 初始化
                BROKER_URL='redis://:sunck@127.0.0.1:6379/0'
                CELERY_IMPORTS=('myApp.task')
            在应用目录下创建task.py文件
            迁移生成celery需要的数据库表:python manage.py migrate
            在工程目录下的project目录下创建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))
            在工程目录下的 project目录下的 __init__.py文件中添加
上一篇下一篇

猜你喜欢

热点阅读