• 19 Jun 18 Django


    19 Jun 18

    一、作业讲解(代码统计)

    # views.py

     

    from django.shortcuts import HttpResponse,render,redirect

    import shutil

    import os

    import uuid

     

    # 导入settings的方式

    from django.conf import settings

     

    ACCEPT_FILE_TYPE  = ['zip','tar','gztar','bztar','xztar','rar'] # 可以给一个全局变量,放在配置文件中,用之前导入

     

    def upload(request):

        if request.method == 'POST':

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

            filename, suffix = file_obj.name.rsplit('.',maxsplit=1)

            if suffix not in ACCEPT_FILE_TYPE: # 增加强健性

                return HttpResponse('wrong file type')

            with open(file_obj.name,'wb') as f:

                for chunk in file_obj.chunks():  # 从上传文件对象一点一点读取数据

                    f.write(chunk)

            real_file_path = os.path.join(settings.BASE_DIR,file_obj.name)  # 拼接得到上传文件的全路径

            upload_path = os.path.join(settings.BASE_DIR,'files',str(uuid.uuid4()))  # 对上传的文件做处理

            shutil.unpack_archive(real_file_path,extract_dir=upload_path)  # 解压代码文件至指定文件夹

            total_num = 0

            for (dir_path,dir_names,filenames) in os.walk(upload_path):

            # os.walk() 用来遍历所有的文件,可以拿到以下三个参数

            # dir_path: 根目录dir_names: 文件夹filenames: 文件

                for filename in filenames:

                    file_path = os.path.join(dir_path,filename)  # 将文件名和根目录拼接成完整的路径

                    file_path_list = file_path.rsplit('.',maxsplit=1)

                    if len(file_path_list) != 2:

                        continue

                    if file_path_list[1] != 'py':

                        continue

                    line_num = 0

                    with open(file_path,'r') as f:

                        for line in f:

                            if line.strip().startswith('#'):

                               continue

                            line_num += 1

                    total_num += line_num

            return

    render(request,'done.html',{'file_name':file_obj.name,'file_size':file_obj.size,'total_num':total_num})

        return render(request,'upload.html')

    二、内容补充

    目前,this和箭头函数一起使用可能出现问题。所以,推荐尽量少用箭头函数;但要能看懂。

     

    三、今日内容

    1. 模版语言剩下的

    http://www.cnblogs.com/liwenzhou/p/7931828.html

    1. csrf_token: 用于跨站请求伪造保护。是Django提供的一个解决方案:在提交表单时带着之前Django给该页面生成的token,如果没有token,或token匹配失败,将拒绝继续访问;这样,钓鱼网站就不可以通过单单设置action,而跳转至正经网站某个页面,进而修改正经网站的数据库。

    在页面的form表单里面写上{% csrf_token %},在settings中即可不注释csrf相关

     

    #钓鱼网站html

    <h1>这是一个钓鱼网站</h1>

    <formaction="http://127.0.0.1:8000/zhuanzhang/"method="post">

    # action直接跳转到别的网站

        <p>转给谁:<input type="text"></p>

        <p><input style="display: none" type="text" name="id" value="3"></p>

        <p>转多少:<input type="text" name="num"></p>

        <p>密码:<input type="password" name="pwd"></p>

        <p><input type="submit" value="提交"></p>

    </form>

     

    #正经网站html

    <h1>这是一个正经网站</h1>

    <formaction="/zhuanzhang/"method="post">

        {% csrf_token %}  # 阻止跨站请求伪造

        <p>转给谁:<input type="text" name="id"></p>

        <p>转多少:<input type="text" name="num"></p>

        <p>密码:<input type="password" name="pwd"></p>

        <p><input type="submit" value="提交"></p>

    </form>

     

       ps:如果不设置数据库,使用默认的数据库db.sqlite3

     

    1. 静态文件相关(取代硬编码(/static/…))

    如果有改static这个名字的需求,用硬编码要通篇改;如果使用以下方式,则不存在这个问题;一般来说,上述需求比较不常见

    {% load static %}

    <img src="{% static "images/hi.jpg" %}" alt="Hi!" />

     

    引用JS文件时使用:

    {% load static %}

    <script src="{% static "mytest.js" %}"></script>

     

    某个文件多处被用到可以存为一个变量

    {% load static %}

    {% static "images/hi.jpg" as myphoto %}

    <img src="{{ myphoto }}"></img>

     

    1. get_static_prefix

    # 极少使用

    {% load static %}

    <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

     

    {% load static %}

    {% get_static_prefix as STATIC_PREFIX %}

    <img src="{{ STATIC_PREFIX }}images/hi.jpg"alt="Hi!" />

    <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

     

    1. 自定义simpletag和自定义filter类似,只不过接收更灵活的参数。

    自定义的filter,simpletag和inclusion_tag都要放在templatetags 这个新建的package中的py文件下

    filter: {{ }}   在变量的基础上做额外的调整

    simpletag  {% %}  可传多个参数,返回它们之间所做运算的结果

    定义注册simple tag

    @register.simple_tag(name="plus")

    def plus(a, b, c):

    return "{} + {} + {}".format(a, b, c)

     

    使用自定义simple tag

    {% load app01_demo %}

    {% plus "1" "2" "abc" %}

     

    1. inclusion_tag:多用于返回html代码片段;后续项目会使用

    # templatetags/my_inclusion.py

     

    from django import template

    register = template.Library()

     

    @register.inclusion_tag('result.html')

    def show_results(n):

        n = 1 if n < 1 else int(n)

        data = ["第{}项".format(i) for i in range(1, n+1)]

        return {"data": data}

     

    templates/snippets/result.html

     

    <ul>

      {% for choice in data %}

        <li>{{ choice }}</li>

      {% endfor %}

    </ul>

     

    templates/index.html

     

    <!DOCTYPE html>

    <html lang="en">

    <head>

     <meta charset="UTF-8">

     <meta http-equiv="x-ua-compatible" content="IE=edge">

     <meta name="viewport" content="width=device-width, initial-scale=1">

     <title>inclusion_tag test</title>

    </head>

    <body>

    {% load inclusion_tag_test %}

    {% show_results 10 %}

    </body>

    </html>

     

    1. urls.py(路由系统)

    http://www.cnblogs.com/liwenzhou/p/8271147.html

        a. URLconf配置

        # 基本格式:

        from django.conf.urls import url

     

        urlpatterns = [

        url(正则表达式, views视图函数,参数,别名),

        ]

     

         # 在Django2.0 中用path替换了url(from django.urls import path)

     

        b. 正则表达式详解

           1)urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。

           2)若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。

           3)不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是^/articles。

              # Django settings.py配置文件中默认没有APPEND_SLASH 这个参数,但 Django 默认这个参数为APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。可设置APPEND_SLASH = False,改变默认值。

           4)每个正则表达式前面的'r' 是可选的但是建议加上。

     

        c. 正则匹配的模式

            1) 分组匹配      --> 调用视图函数的时候额外传递位置参数;正则表达式分组匹配(通过圆括号)来捕获URL中的值并以位置参数形式自动传递给视图的args。

               # *args, agrs = (a,b)

               url(r'^articles/([0-9]{4})/$', views.year_archive),

     

            2) 分组命名匹配   --> 调用视图函数的时候额外传递关键字参数

               url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

     

            注意:

               a) 要么全都用分组匹配,要么全都用分组命名匹配,不要混着用!

               b) Django utl正则表达式匹配的位置:从第一个斜线到问号之前这一段的路径

               c) URL正则表达式捕获的值都是字符串类型,如果要参与后续运算,应先进行类型转换。

               d) 可以给视图函数的参数设置默认值

    # 正则匹配时,不论是否分组带参数,即都可以调用views中的page方法

                   # urls.py中

                   from django.conf.urls import url

                   from . import views

     

                   urlpatterns = [

                       url(r'^blog/$', views.page),

                       url(r'^blog/page(?P<num>[0-9]+)/$', views.page),

                   ]

     

                   # views.py中,可以为num指定默认值

                   def page(request, num="1"):

                       pass

     

        d. include 分级路由(级级匹配:/app01/upload; 在第一级匹配app01,在第二级匹配upload)

           # 推荐在各个app下建立自己的urls.py

           查找的顺序:请求--> project/urls.py  --> app/urls.py  --> app/views.py

     

           from django.conf.urls import include, url

     

           urlpatterns = [

              url(r'^admin/', admin.site.urls),

              url(r'^blog/', include('blog.urls')),  # 可以包含其他的URLconfs文件

           ]

     

        e. 传递额外的参数给视图函数

           from django.conf.urls import url

           from . import views

     

           urlpatterns = [

              url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),

           ]

     

        f. URL匹配规则的别名(命名URL和URL反向解析(别名->正则表达式(URL)))

            1) 起别名是为了,增加代码的健壮性,不将URL硬编码到代码中!

     

            2) 用法

                a) 在views.py中如何根据别名找到url

                    from django.urls import reverse

                    url = reverse('别名')

     

                b) 在模板语言中如何根据别名找到url

                    {% url '别名' %}

     

            3) 带参数的url如何反向生成?

                a) 位置参数

                    i) 在views.py中:

                        reverse("别名", args=(参数1, 参数2, ...))

     

                    ii) 在模板语言中:

                        {% url "别名" 参数1, 参数2... %}

     

                b). 关键字参数

                    i) 在views.py中:

                        reverse("别名", kwargs={"k1":参数1, ...})

     

                    ii) 在模板语言中:

                        {% url "别名" 参数1, 参数2... %}

                        # 在模版语言中,无法传递关键字参数,只能根据位置,依次传参

     

            4) namespace(命名空间), 是include的一个参数

               # 使用include语法,将其他的urls.py 包含进来

                from django.conf.urls import url, include

     

                urlpatterns = [

                   url(r'^app01/', include('app01.urls', namespace='app01')),

                   url(r'^app02/', include('app02.urls', namespace='app02')),

                ]

     

                语法:'命名空间名称:URL名称'

     

                # 这样两个app中url名称重复了,反转URL的时候就可以通过命名空间的名称得到当前的URL;即使app中URL的命名相同,也可以反转得到正确的URL了。

                模板中使用:

                {% url 'app01:detail' pk=12 pp=99 %}

     

                views中的函数中使用

                v = reverse('app01:detail', kwargs={'pk':11})

     

    四、今日作业

    用一个函数一个URL匹配模式实现 书书籍表、作者表、出版社表的展示和删除操作

    关键点:

    1. URL匹配模式的设计(分组匹配或分组命名匹配;给URL匹配模式起别名)

    2. 反射:由一个字符串,找到对应的类变量

    3. URL的反向解析(别名--> 完整的URL)

    4. 正则表达式

    import re

    # 写一个正则表达式, 只能从add delete edit list  这四个单次里面选一个

    s1 = "delete"  # 匹配成功

    s2 = "cut"  # 匹配不成功

     

    r = re.compile(r'add|delete|edit|list')

    print(r.match(s1))

    print(r.match(s2))

     

    # urls.py

    url(r'(?P<operation>list|delete)_(?P<table_name>[a-zA-Z]+)/', views.op, name = 'list_delete'),

     

    # views.py

    def op(request,operation,table_name):

        table = table_name.capitalize()

        if hasattr(models,table):

            class_obj = getattr(models,table)

            if operation.upper() == 'LIST':

                ret = class_obj.objects.all()

                return render(request,'{}_{}.html'.format(table_name,operation),{'ret':ret})

            elif operation.upper() == 'DELETE':

                id = request.GET.get('id')

               class_obj.objects.get(id=id).delete()

                url = reverse('list_delete', kwargs={'operation':'list','table_name':table_name})

                return redirect(url)

  • 相关阅读:
    jQuery火箭图标返回顶部代码
    质数和分解(完全背包)
    CodeForces
    FZU
    FZU
    Pets(匈牙利算法)
    Construct a Matrix (矩阵快速幂+构造)
    绝世好题(线性dp)
    String painter (区间dp)
    Funny Positive Sequence (思维+前缀)
  • 原文地址:https://www.cnblogs.com/zhangyaqian/p/py20180619.html
Copyright © 2020-2023  润新知