Django day03之学习知识点


今日是路由层学习:

3.路由匹配
    3.1     正则表达式的特点:
        一旦正则表达式能够匹配到内容,会立刻结束匹配关系
        直接执行对应的函数。相当于采用就近原则,一旦找到就不再继续往下走了
        重点:
            正则表达式开头用 ^ 表示 (开头必须要有)
            正则表达式结尾用 $ 表示
            urlpatterns = [
                url(r'^admin/', admin.site.urls),
                url(r'^test/', views.test),
                url(r'^testadd/', views.testadd),
            ]

    3.2    settings.py文件中配置请求的访问路径自动加斜杠的功能
    默认情况下,是TRUE。
    #取消django自动让浏览器加斜杠的功能
            APPEND_SLASH = False
    添加配置后
    例如:
        http://127.0.0.1:8000/testadd进行请求会出现404页面
    取消配置后,尾部django会自动添加/
        http://127.0.0.1:8000/testadd/ 请求访问成功

    举例:
        1.路径如下:
        urlpatterns = [
                url(r'^admin/', admin.site.urls),
                url(r'testadd/', views.testadd),
            ]
    请求路径中的漏洞:
    http://127.0.0.1:8000/wwwwwwwwwwwwwtestadd/
    请求结果:请求成功
    解决方法:
    在url(r'testadd/', views.testadd)中的testadd/前部添加 ^ 符号
    代表请求路径  从...开始
    正确路径如下:
        urlpatterns = [
                url(r'^admin/', admin.site.urls),
                url(r'^testadd/', views.testadd),
            ]

    2.路径如下:
    urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^testadd/', views.testadd),
        ]
    请求路径中的漏洞:
    http://127.0.0.1:8000/testadd/wwwwwwwwww
    请求结果:请求成功
    解决方法:
    在url(r'^testadd/', views.testadd)中的testadd/尾部添加 $ 符号
    代表请求路径  以...结束
    正确路径如下:
        urlpatterns = [
                url(r'^admin/', admin.site.urls),
                url(r'^testadd/$', views.testadd),

            ]

    注意事项:
        路由匹配只匹配请求的url路径部分,不匹配 ?后面的get携带的字段值参数,如下:
        http://127.0.0.1:8000/testadd/?username=jsaon

4.无名分组---->用位置形参
        urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^test/([0-9]{4})', views.test),
        url(r'^testadd/', views.testadd),
    ]
    对应报错的语句:
    url(r'^test/([0-9]{4})', views.test),
    test() takes 1 positional argument but 2 were given
    什么是无名分组?
        当你的路由中有分组"([0-9]{4})"的正则表达式,那么在匹配到内容时执行函数的时候,
        会将分组内正则表达式匹配到的内容当做位置参数传递给视图函数,那么
        就需要在函数中添加一个形参,如下:
        def test(request,分组对应的形参):

5.有名分组----->用关键字实参
    (?P<year>\d+)
        urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^testadd/(?P<year>\d+)', views.testadd),
    ]

    url(r'^testadd/(?P<year>\d+)', views.testadd),
    testadd() got an unexpected keyword argument 'year'

    什么是有名分组?
    当你的路由中有分组并且给分组起了别名(year),那么在匹配内容的时候,
    会将分组内的正则表达式匹配到的内容(year)当做关键字参数传递给视图函数,
    def testadd(request,year):
    year的值是用户在浏览器输入的url地址中对应的一块数据
    比如用户输入的地址是:http://127.0.0.1:8000/testadd/2222,请求成功,
    那么year对应的数据就是   year=2222
    关键字参数:
        def func(x,y):
            print(x)
            print(y)
        func(x=1,y=2)
    位置参数:
        def func(x,y):
            print(x)
            print(y)
        func(1,2)

    利用有名和无名分组,我们就可以在调用视图函数之前给函数传递额外的参数。
    django中有名分组和无名分组不能同时混合使用!!!
    但是同一种分组的情况下,可以使用多次,
    无名可以有多个,
    有名可以有多个,
    但是就是不能混合使用,其实写多个也没有啥意思,知道这种形式即可
        url(r'^index/(\d+)/(\d+)/',views.index)
        url(r'^index/(?P<args>\d+)/(?P<args>\d+)/',views.index)

6.第一种情况反向解析
(通俗)何为反向解析,就是通过A---->(访问到了)B去了!!!
(专业)何为反向解析,就是根据一个别名,动态解析出一个结果,
该结果可以最直接访问到对应的url

        1.前端反向解析: 在html页面中编写
                {% url 'xxx' %}
            <p><a href="{% url 'xxx' %}">111111</a></p>

        2.后端反向解析:  在views.py文件中编写
            1.首先导入reverse模块:
            from django.shortcuts import render,HttpResponse,redirect,reverse
            2.在对应视图函数中编写后端反向解析代码
                url=reverse('xxx')

7.第二种情况反向解析
        1.无名分组的反向解析,在解析的时候,你需要手动指定正则匹配的内容是什么
            url(r'^home/(\d+)', views.home,name='xxx'),

            Reverse for 'xxx' with no arguments not found. 1 pattern(s) tried: ['home/(\\d+)']
            翻译:'xxx'的反转,没有找到参数。['home/(\\d+)']

            解决方法:
                在前端对应的html文件中,解析代码中添加一个匹配正则的参数即可(例如:12)
                   {% url 'xxx' 12 %}
                   该数字通常是数据的主键值!!!
            <p><a href="{% url 'xxx' 12 %}">111111</a></p>
            注意事项:在后端views.py文件中配置一个位置参数(yyy)接收正则
            def home(request,yyy):
                return HttpResponse('Home')
        综上所述,所以总结如下:
            无名分组前端反向解析:
                <p><a href="{% url 'xxx'  12 %}">111111</a></p>

            无名分组后端反向解析:
                后端反向解析需要后端views.py文件中,对应的函数中的位置参数匹配到正则表达式即可

                通过访问http://127.0.0.1:8000/index/,点击'111111',跳转报错,
                报错信息:home() takes 1 positional argument but 2 were given
                原因是home函数缺少了一个位置参数,所以下面的home函数需要配置一个位置参数(yyy)
                1.def home(request,yyy):
                    return HttpResponse('Home')
                之后后端对应解析如下:
                添加一个args=(参数,),注意括号内的逗号不能省略
                2.def get_url(request):
                    url=reverse('xxx',args=(1,))    #必须加逗号,作为元组
                    print(url)
                    return HttpResponse('get_url,大宝贝')
                在get _url函数中,如果反转解析忘记配置args =(参数,)了,就会报下面的错误:
                    Reverse for 'xxx' with no arguments not found. 1 pattern(s) tried: ['home/(\\d+)']
                    'xxx'的反转,没有找到参数。

8.第三种情况反向解析
无名分组不是真的无名,而是没有固定的名字;
有名分组是因为有固定不变的名字,所以称之为有名分组;
下面的知识点仅作了解:
        1.有名分组的反向解析,在解析的时候,需要手动指定,正则匹配的内容是什么呢?
        正规的写法是:
            url(r'^home/(?P<year>\d+)', views.home,name='xxx'),
        前端:
            可以直接用无名分组的情况
            <p><a href="{% url 'xxx'  12 %}">111111</a></p>
            也可以使用规范的写法!!!书写麻烦了解即可
            <p><a href="{% url 'xxx'  year=1232 %}">111111</a></p>

        后端:
            可以直接用无名分组的情况
            url=reverse('xxx',args=(1,))
            也可以使用规范的写法!!!书写麻烦了解即可
            url=reverse('xxx',kwargs={'year':666})

9.无名有名反向解析结合使用
        以编辑功能为例
        url(r'^edit_user/(\d+)/',views.edit_user,name='edit')

        def edit_user(request,edit_id):
            #edit_id就是用户想要编辑数据的主键值
            pass
        {% for user_obj in user_list %}
        <a href='/edit_user/{{user_obj.id}}'>编辑</a>
        <a href='{% url 'edit' user_obj.id %}'>编辑</a> #反向解析
        {% endfor %}

10.路由分发
        前提:
                在django中所有的app都可以有自己独立的urls.py  templates  static文件
            作用:为大项目解耦合,分功能开发,互相之间不干扰,每个人只负责自己的app即可
            项目经理只需要将所有人开发的app整合到一个空的django项目中,
            然后再settings配置文件注册,再利用路由分发将多个app整合到一起,
            即可完成大项目的拼接。

        路由分发解决的就是项目的总路由匹配关系过多的情况
        使用路由分发,会将总路由不再做匹配的活而仅仅是做任务分发:
            请求来了之后,总路由不做对应关系,只询问你要访问哪个app的功能,
            然后将请求转发给对应的app去处理。
        创建第二个app
            1.Tools--->Run manage.py Task...
            2.manage.py@day51 > startapp app02
            然后在settings配置文件中配置对应app名字
            INSTALLED_APPS = [
                'django.contrib.admin',
                'django.contrib.auth',
                'django.contrib.contenttypes',
                'django.contrib.sessions',
                'django.contrib.messages',
                'django.contrib.staticfiles',
                'app01.apps.App01Config',
                'app02'
            ]
            并分别在app下创建urls.py文件
            3.
            总路由只需要将所有的app的urls.py导入即可。
            总路由中导入include模块:
            from django.conf.urls import url,include
            总路由中导入各个应用下的urls.py文件,as 是起别名:
            from app01 import urls as app01_urls
            from app02 import urls as app02_urls
            在对应的应用下的urls.py文件中书写下面代码:
            例如:app01应用的urls.py文件中书写:
            from django.conf.urls import url
            from app01 import views
                urlpatterens = [
                    #这里面写该应用下的路由
                    url(r'^index/', views.index)

                ]

        总路由分发:
            总路由中使用include做分发
            因为app01、app02下的路由、对应视图函数都含有def reg(request):函数,
            所以总路由为了做好区分,在总路由中分别使用各个应用名的前缀来做区分,

        笨方法总路由:
            from django.conf.urls import url,include
            from app01 import urls as app01_urls
            from app02 import urls as app02_urls
            urlpatterns = [
                url(r'^app01/',include(app01_urls)),
                url(r'^app02/',include(app02_urls))
            ]
            总路由分发注意事项:
                总路由里面不能以 $ 符号结尾
                在urlpatterns中r'^app02/'$(千万不能加$符号),不然路径都是匹配不上的
        为了解决总路由中每次频繁导入app应用的问题:
        django推出了最最简单的总路由分发方法:
            特点:
                1.无需频繁导入
                2.不用频繁加应用名后缀
            那么该方法是什么呢?
        新方法总路由:
            1.不要导入语句
            2.不再使用应用名前缀,使用 (应用名.urls)
            #from app01 import urls as app01_urls
            #from app02 import urls as app02_urls
            from django.conf.urls import url,include
            urlpatterns = [
                url(r'^app01/',include(app01.urls)),
                url(r'^app02/',include(app02.urls))
            ]
        ||||||||||||||筛检上面不用的代码,如下:||||||||||||||||||
            from django.conf.urls import url,include
            urlpatterns = [
                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'^reg/', views.reg),
            ]

        子路由app02:
            from django.conf.urls import url
            from app02 import views
            urlpatterns = [
                url(r'^reg/', views.reg),
            ]
    路由分发:
            前提:
                所有的app都可以有自己独立的urls.py  templates模板文件夹  static静态文件夹
                正是由于该特点,使得django实现多人开发 非常方便
                每个人只需要开发自己的app即可

            路由分发:
                总路由不再直接做路由与试图函数对应关系了,而是仅仅做一个转发的功能
                好处:更加的解耦合,更加好维护
                from django.conf.urls import url,include
                url(r'^应用名1/',include('应用名1.urls'))
                url(r'^应用名2/',include('应用名2.urls'))


11.名称空间--了解知识点,记住最后面两句话
        当不同的应用中给路由与视图对应关系起了相同的别民,在反向解析的时候,并不能
        直接识别到时哪个应用下的
        url(r'^应用名1/',include('应用名1.urls',namespace='应用名'))
        {% url '应用名1:相同的别名' %}
        {% url '应用名2:相同的别名' %}

        记住这两句话:
            你完全可以不使用名称空间,
            你只需要保证在起别名的时候,不要出现冲突即可,
            建议做法就是加 应用前缀_别名

12.虚拟环境
        给每一个喜爱你干嘛提供一个专门属于该项目自己的所需模块,避免浪费,节省资源
        requirement.txt
            django==1.11.11
            Flask==1.4
            建议不要频繁的开设虚拟环境
            虚拟环境创建中选择 New environment--->Make available to all projects


        django版本区别:
            path 与 url
            path 第一个参数不支持正则,如果你还想使用正则,你可以re_path和url是一模一样的
            path虽然不支持正则,但是提供了五个默认的转换器,能够自动帮你转换数据类型
            还支持用户自定义转换器
            
        request方法获取文件数据:
            request.FILES  获取form表单上传的文件数据
            
            file_obj=request.FILES.get('myfile')
            file_obj.name --->文件名
            
            f=open(file.obj.name,'wb')
            for chunk in file_obj.chunks():
                f.write(chunk)
            f.close()
            
            
            




















posted @ 2019-11-26 20:27  大海一个人听  阅读(249)  评论(0编辑  收藏  举报