zoukankan      html  css  js  c++  java
  • Django之路由层、视图层、模板层介绍

    一、Django请求生命周期

    1.路由层urls.py

    Django 1.11版本 URLConf官方文档

    1.1 urls.py配置基本格式

    from django.conf.urls import url
    
    urlpatterns = [
         url(正则表达式, views视图函数,参数,别名),
    ]

    1.11.x版本默认

    from django.conf.urls import url
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
    url(r'^test/$', views.test),
    ] 
    # 获取到用户输入的url后,根据正则匹配是否对应
    # http://127.0.0.1:8000/test 请求的时候实际是请求了2次,第一次请求是按照浏览器输入的进行请求,但是没有匹配到,第二次请求浏览器会自动在末尾加一个/之后进行匹配,如果还匹配不上直接报错
    # 注意事项
    1 urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
    2 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
    3 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
    4 每个正则表达式前面的'r' 是可选的但是建议加上。
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        # url(r'test/[0-9]{4}/$', views.test),
        # 无名分组:会将分组内的结果 当做位置参数自动传递给后面的视图函数views.py
        url(r'test/([0-9]{4})/$', views.test),
        # url(r'^test/(d+)/$',views.test),
        # 有名分组:会将分组内的结果 当做关键字参数自动传递给后面的视图函数
        url(r'^testadd/(?P<id>[0-9]{4})/$',views.testadd),
    ]
    # 无名分组:http://127.0.0.1:8000/test/3333/,视图函数加参数后可以访问,如果不加会提示test() takes 1 positional argument but 2 were given
    # 有名分组

     1.2 反向解析

      根据别名动态解析出可以匹配上视图函数之前的url的一个结果(注意:在起别名的时候,一定要保证 所有的别名都不能重复,必须是唯一的)

    # urls.py
        url(r'^testxxx/',views.test,name='t')
        url(r'^test/(d+)/$',views.test,name='ttt'),
    
    # 前端
        没有正则表达式的反向解析
        {% url 't' %}
        无名分组反向解析
        有名分组同上
       有正则表达式的反向解析
       {% url 'ttt' 1 %} # 数字通常是数据库中字典的pk值
    # 后端 from django.shortcuts import render,HttpResponse,redirect,reverse 没有正则表达式的反向解析 reverse('t')
       无名分组反向解析 reverse(
    'ttt',args=(1,)) #有正则表达式的反向解析函数视图views.py 有名分组同上 # urls.py中使用别名后,testxxx无论怎么变,浏览器中路径也会自动变化,动态解析到前端

    有名分组和无名分组能否混合使用?
    ---有名无名不能混合使用!!!

    1.3 页面伪静态

    # 伪静态
        让一个动态页面伪装成一个看似数据已经写死了的静态页面,其实是经过了视图函数处理,动态渲染的页面
        好处:让搜索引擎加大对你这个页面的收藏力度,当别人搜索你这个页面相关内容,提高优先展示概率(花钱最好)
        加大seo查询

    # 例如:在urls.py中将路由设置成,视图函数views.py中还是不变:return HttpResponse("index.html")
    url(r'^index.html$',views.index),
    例如:10982293.html https://www.cnblogs.com/Dominic-Ji/articles/10982293.html

     1.4 django版本区别1.x与2.x

    1.X
        路由里面用的是url()
    2.X
        路由里面的用的是path()
        url第一个参数放的是正则表达式
        而你的path第一个参数写什么就是什么,不支持正则
        如果你还想使用第一个参数是正则的方法
        django2.X版本中有一个叫re_path()
        ps:2.x中re_path就等价于1.x中的url
            
        # 虽然path不支持正则表达式,但是它提供了五种转换器(了解)

    1.5 路由分发

        当一个django项目下面有多个app的情况下,总的urls.py中路由与视图函数的对应关系太多 不便于管理
    这个时候就可以再每个app下创建自己的urls.py,总的urls.py不再做对应关系,而只是做分发任务 每个app下都可以有自己的urls.py static文件夹 templates模板文件,也就意味着 每个app都可以被独立的开发出来 而不需要讨论交互
    #  路由分发:根据前缀,去对应的目录下查找路由
    
    # 总路由下urls.py配置
    # 重名的使用别名
    from django.conf.urls import url,include
    from app01 import urls as app01_urls
    from app02 import urls as app02_urls
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^app01/',include(app01_urls)),
        url(r'^app02/',include(app02_urls)),
    ]
    
    # 应用app01下的路由
    from django.conf.urls import url
    from app01 import views
    
    urlpatterns = [
        url(r'^urlindex',views.urlindex),
    ]
    
    # app01下的视图函数views.py
    from django.shortcuts import render,HttpResponse,redirect
    
    def urlindex(request):
        return HttpResponse("app01下的index")
    
    # 应用app02下的路由
    from app02 import views
    
    urlpatterns = [
        url(r'^urlindex',views.urlindex)
    ]
    
    # app02下的视图函数views.py
    from django.shortcuts import render,HttpResponse,redirect
    
    def urlindex(request):
        return HttpResponse("app02下的urlindex")
    
    # 访问app01下的链接:http://127.0.0.1:8000/app01/urlindex
    # 访问app02下的链接:http://127.0.0.1:8000/app02/urlindex
    # 都可以显示对应的提示

    # 如果2个app下起了相同的名字,那么反向解析不支持自动查找应用前缀,需要了解名称空间的概念
    # app01
    urlpatterns = [
        url(r'^urlindex',views.urlindex,name='aaa')
    ]
    # app02
    urlpatterns = [
        url(r'^urlindex',views.urlindex,name='aaa')
    ]
    # views.py中都打印下print('aaa')
    # 访问app01和app02的urlindex后端打印的都是一样的
    
    # 第一种方法:
    # 反向解析的时候可以在name='aaa'中添加前缀解决
    # 例如:name='app01_aaa'
    
    # 第二种方法:
    # 名称空间(了解既可):在分发的时候再起一个名字
    # 总路由urls.py中
    urlpatterns = [
        url(r'^app01/',include(app01_urls,namespace='app01')),
        url(r'^app02/',include(app02_urls,namespace='app02')),
    ]
    
    #app01中的路由urls.py
    urlpatterns = [
        url(r'^urlindex',views.urlindex,name='aaa')
    ]
    # app01的views.py
    def urlindex(request):
        print(reverse('app01:aaa'))
        return HttpResponse("app01下的index")
    # app02的路由
    urlpatterns = [
        url(r'^urlindex',views.urlindex,name='aaa')
    ]
    # app02的views.py
    def urlindex(request):
        print(reverse('app02:aaa'))
        return HttpResponse("app02下的urlindex")
    
    # 然后分别访问就正常了

    # 使用importlib方法:


    2. 视图层

    2.1 JsonResponse

    # views.py
    import json
    def index(request):
        d = {'name':'simon','password':'123','hobby':'读书'}
        # 前端不支持字典,需要转成json格式
        return HttpResponse(json.dumps(d,ensure_ascii=False))
    # 前端页面显示:http://127.0.0.1:8000/index/
    {"name": "simon", "password": "123", "hobby": "读书"}
    
    # 第二种方式:
    from django.http import JsonResponse
    def index(request):
        d = {'name':'simon','password':'123','hobby':'读书'}
        # 前端不支持字典,需要转成json格式
        # return HttpResponse(json.dumps(d))
        return JsonResponse(d)
    
    # JsonResponse直接转换成json格式
    # 前端没显示中文,可以通过JsonResponse源代码来看方法
    # return JsonResponse(d,json_dumps_params={'ensure_ascii':False})

    2.2 FBV与CBV

    FBV function based views

    CBV class based views

    # views.py
    from django.views import View
    class MyLogin(View):
        def get(self,request):
            return HttpResponse("Get")
    
        def post(self,request):
            return HttpResponse("Post")
    
    # urls.py中如何添加路径?
    # CBV路由配置
    url(r'^login/',views.MyLogin.as_view()),
    
    # 可以在前端home.html写一个页面测试post提交方式
    <form action="/login/" method="post">
        <input type="submit">
    </form>
    
    # 可以看到我们访问login直接返回Get
    #     访问home.html点击提交就会跳到login页面显示post
    # 可以看到get请求来走get,post请求走post

    3.模板层

     模板语法--模板传值

    # 模板语法 url.py
    url(r'^demo/',views.demo),
    # views.py
    def demo(request):
        i = 1
        f = 1.11
        s = 'hello'
        # s = []
        l = [1,2,3,4,5,6,7,8,9]
        t = (1,2,3,4)
        d = {'name':'simon','password':'123'}
        se = {1,2,3,4}
        # 通过字典传值方式
        # return render(request,'demo.html',{'xxx':[1,2,3,4]})
        
        def foo():
            print("foo")
            return "0000000oooooooooo"
    
        class Demo(object):
            def index(self):
                return 'index'
    
            @classmethod
            def login(cls):
                return 'cls'
    
            @staticmethod
            def reg():
                return 'reg'
    
        obj = Demo()
        return render(request,'demo.html',locals())  # locals 会将所在名称空间中的所有名字全部传递给前端页面
    
    # 前端页面
    # 第一种传值方式
    return render(request,'demo.html',{'xxx':[1,2,3,4]})
    # 前端使用
    {{ xxx }}
    
    # 第二种传值方式
    # locals 会将所在名称空间中的所有名字全部传递给前端页面
    return render(request,'demo.html',locals())
    # 前端页面需要将所有定义的:i f s等使用双大括号括起来显示
    # 如果是函数传到前端显示
    <p>{{ foo }} 如果是函数名,传递到前端会自动加()调用,将调用后的结果展示到前端页面</p>
    #如果是类
    {#<p>{{ obj.index }} 只要是方法 都会自动加括号调用</p>#}

    # 获取列表字典中某一个值
    前端{{ l.0 }} or {{ d.name }}

     3.1.过滤器

    # 后端3中demo类中直接定义n和i
        import datetime
        ctime = datetime.datetime.now()
        sss = 'sadfasf sdfasf fasdfsadf sdfa'
    
    # 前端:
    {{i|add:19}}  # 结果:20
    {{n|filesizeformat}}  # n的值进行转化成文件大小M、G等
    {{ ctime|date:'Y-m-d' }}  # 日期获取
    {{ sss|truncatechars:20 }} # 截断一部分...来省略(20包含3个点)
    {{ sss|truncatewords:2 }}  # 截断,只识别空格
    #后端
    def demo(request):
        h = "<h1>我是h1标签</h1>"
        s1 = "<script>alter(123)</script>"
        # 后端转义views.py
        from django.utils.safestring import mark_safe
        s2 =  "<h2>我是h2标签</h2>"
        s2 = mark_safe(s2)  # 这样前端就不需要用safe了
    
    # safe告诉前端我这个代码是安全的,可以渲染
    # 前端转义
    {{ h|safe }}
    {{ s1 }}  # 这个如果加safe,前端就会死循环
    {{ s2 }}

    3.2 标签

    # 后端
    def demo(request):
        l = [1,2,3,4,5,6,7,8,9]
        s3 = [1,2]
        s4 =[None,1]
    
    # 模板语法的if判断    
    # 前端demo.html
    {% if s3 %}
        <p> 有值{{ s3 }}</p>  # 返回结果就是这个了
        {% else %}
        <p>这个东西是空的</p>
    {% endif %}
    {% if s4.0 %}
        <p> 有值{{ s4 }}</p>
        {% elif s4.1 %}
        <p>没值</p>
        {% else %}
        <p>这个东西是空的</p>
    {% endif %}
    # 就算值取不到也不会报错
    
    {% for foo in l %}
    {#    # foo为每次列表循环的元素,first为第一个值,last为最后一个值,中间可以#}
        {% if forloop.first %}
                <p>first...</p>
            {% elif forloop.last %}
                <p>这是last</p>
            {% else %}
                <p>继续啊~~~</p>
        {% endif %}
        {% empty %}
            <p>是空的,不能循环</p>
    {% endfor %}

    3.3 模板的继承与导入

    # 模板的继承
    # 在你想做成模板的页面上 添加block块儿 来标识其他用户可以占用的区域
    {% extends 'tmp.html' %}
    
        {% block content %}
                    <div class="jumbotron">
                      <h1>Hello, world!</h1>
                      <p>...</p>
                      <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
                    </div>
            {% endblock %}
    # 先在模板中划定区域,之后子板利用block就能够找到模板中可以被使用的区域
    
    # 通常情况下 模板中最少有三个区域
    css
    content
    js
    ps:模板中的block块儿越多 页面的可扩展性越高
    # 模板的导入
    将一块html页面作为模块的方式 导入使用
    {% include 'goodpage.html' %}
    将goodpage.html页面内容直接导入到该语句的位置
    # 模板的继承与导入
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
        <link href="/static/bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet">
        <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
    </head>
    <body>
    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">Brand</a>
            </div>
    
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                    <li><a href="#">Link</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                           aria-expanded="false">Dropdown <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">One more separated link</a></li>
                        </ul>
                    </li>
                </ul>
                <form class="navbar-form navbar-left">
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Search">
                    </div>
                    <button type="submit" class="btn btn-default">Submit</button>
                </form>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">Link</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                           aria-expanded="false">Dropdown <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                        </ul>
                    </li>
                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-3">
                <div class="list-group">
                    <a href="/loginn/" class="list-group-item active">登录</a>
                    <a href="/register/" class="list-group-item">注册</a>
                    <a href="#" class="list-group-item">Morbi leo risus</a>
                    <a href="#" class="list-group-item">Porta ac consectetur ac</a>
                    <a href="#" class="list-group-item">Vestibulum at eros</a>
                </div>
            </div>
            <div class="col-md-9">
                {% block content %}
                <div class="jumbotron">
                    <h1>Hello, world!</h1>
                    <p>...</p>
                    <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
                </div>
                {% endblock %}
            </div>
        </div>
    
    </div>
    </body>
    </html>
    
    # login.html 模板的导入
    {% extends 'tmp.html' %}
    
    {% block content %}
    <h3>登录</h3>
        <form action="" method="post" class="form-group">
            <p>username:<input type="text" class="form-control"></p>
            <p>password:<input type="text" class="form-control"></p>
            <input type="submit" class="btn btn-danger pull-right">
        </form>
    {% endblock %}
    
    # reg.html模板的导入与继承
    {% extends 'tmp.html' %}
    
    {% block content %}
    {#    模板的导入#}
        {% include 'good.html' %}
    <h3 class="text-center">注册</h3>
        <form action="" method="post" class="form-group">
            <p>username:<input type="text" class="form-control"></p>
            <p>password:<input type="text" class="form-control"></p>
            <input type="submit" class="btn btn-danger pull-right">
        </form>
    {% endblock %}
    
  • 相关阅读:
    国外摄影网站
    网络基础之子网划分
    Java-多线程第三篇3种创建的线程方式、线程的生命周期、线程控制、线程同步、线程通信
    Java-多线程第二篇多线程相关认识(2)
    设计模式-第八篇之桥接模式
    设计模式-第七篇之门面模式
    设计模式-第六篇之策略模式
    设计模式-第五篇之命令模式
    设计模式-第四篇之代理模式
    设计模式-第九篇之观察者模式
  • 原文地址:https://www.cnblogs.com/yangmeichong/p/11411360.html
Copyright © 2011-2022 走看看