zoukankan      html  css  js  c++  java
  • Python学习笔记Day19

    路由系统URL

    a. url路由(旧版)

    • 单个参数(d+)

        url(r'^detail-(d+).html', views.detail)
      
    • 多个参数按顺序赋给形参

        url(r'^detail-(d+)-(d+).html', views.detail)
        def func(request, *args, **kwargs):
            args = (2,9)
      
    • 多个参数指定形参 (最常用)

        url(r'^detail-(?P<nid>d+)-(?P<uid>d+).html', views.detail)
        
        def func(request, *args, **kwargs):
            kwargs = {'nid': 1, 'uid': 3}
      

    新版使用path代替

    a. path路由

    • path参数

        path('detail/<int:p>/', views.detail),
        path('articles/2003/', views.special_case_2003),
        path('articles/<int:year>/', views.year_archive),
        path('articles/<int:year>/<int:month>/', views.month_archive),
        path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
      
        def func(request, *args, **kwargs):
                kwargs = {'year': 1, 'month': 3}
        # 参数
            int     -> 匹配0和正整数
            str     -> 匹配任何非空字符串但不包括/,不写默认匹配str
            slug    -> 可理解为注释,匹配任何ascii码,包括连字符-和下划线_
            uuid    -> 匹配一个uuid对象(该对象必须包括破折号—,所有字母必须小写)
            path    -> 匹配所有的字符串 包括/(意思就是path前边和后边的所有)
      
        path里不再需要用r,^,$符号
        默认采用截止符方式,需要后加参数用?
      
    • re_path()

      (?P<var>...) ...中直接写re规则

        re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
        re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
        re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[w-]+)/$', views.article_detail),
      

      两种嵌套参数

        re_path(r'^blog/(page-(d+)/)?$', blog_articles),
        re_path(r'^comments/(?:page-(?P<page_number>d+)/)?$', comments),  # 推荐
      
        # (?:...)为非捕获参数
      

    b. name命名

    对URL进行命名,方便更改、调用和reverse (以后可以根据此名称生成自己想要的URL)

    • url里指定name

        path('asdfasdfasdf/', views.index, name='i1'),
        path('yug/(d+)/(d+)/', views.index, name='i2'),
        path('buy/<int:pid>/<int:nid>/', views.index, name='i3'),
      
    • html里通过name生成url跳转

        ./xxx.html
            action="{% url "i1" %}"                   # asdfasdfasdf/
            action="{% url "i2" 1 2 %}"               # yug/1/2/
            action="{% url "i3" pid=1 nid=9 %}"       # buy/1/9/
            {{request.path_info}}                     # 跳转到当前的URL
      
    • 反转name生成url

        ./views.py
        def func(request, *args, **kwargs):
            from django.urls import reverse
            url1 = reverse('i1')                              # asdfasdfasdf/
            url2 = reverse('i2', args=(1,2,))                 # yug/1/2/
            url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # buy/1/9/
      

    c. 多级路由分发

    • 分发至app

        ./project/urls.py
            from django.conf.urls import url,include
            urlpatterns = [
                path('cmdb/', include("app01.urls")),
                path('monitor/', include("app02.urls")),
            ]
      
        ./app01/urls.py
            from app01 import views
            urlpatterns = [
                path('login/', views.login),
            ]
      
        ./app02/urls.py
            from app02 import views
            urlpatterns = [
                path('login/', views.login),
            ]
      
        # 被包含的URLconf 会收到来自父URLconf 捕获的任何参数
            path('<username>/blog/', include('foo.urls.blog')),
      
    • 同名前缀分组

        from apps.main import views as main_views
        from credit import views as credit_views
      
        extra_patterns = [
            path('reports/', credit_views.report),
            path('reports/<int:id>/', credit_views.report),
            path('charge/', credit_views.charge),
        ]
      
        urlpatterns = [
            path('', main_views.homepage),
            path('help/', include('apps.help.urls')),
            path('credit/', include(extra_patterns)),
        ]
      

    d. 命名空间

    ./project/urls.py
        path('admin/', include('app01.urls',namespace='m1'))
        path('crm/', include('app02.urls',namespace='m2'))
    
    ./app01.urls
        app_name = 'n1'
    
    ./views.py
        reverse('m1:n1', kwargs={'key': 'value'})
    
    # 命名空间可以组合嵌套
    

    e. 默认值

        urlpatterns = [
        path('blog/', views.page),      # 不指定num参数时,默认num=1
        path('blog/page<int:num>/', views.page),
    ]
    
    def page(request, num=1):
        ...
    

    f. 添加额外参数给views (钩子)

    path('index/', views.index, {'name': 'alex'}),      # 传入额外值name = 'alex'
    
    def index(request,name):
        print(name)
        return HttpResponse('OK')
    
    path('blog/', include('inner'), {'blog_id': 3}),    # 为include的所有url传递额外值
    

    模板文件分路由配置

    `'DIRS': [os.path.join(BASE_DIR, 'templates')]`  是指到  BASE_DIR/templates文件夹中去取模板
    `'DIRS': [os.path.join(BASE_DIR, 'app1/templates')]` 是指导  BASE_DIR/app1/templates文件夹中去取模板
    

    一般来说,应该设置'DIRS': [os.path.join(BASE_DIR, 'templates')],公用的templates需要指定。
    app1专用的templates,放在app1/templates下,可以不需指定。
    因为在app1.views中若要指定一个专用模板,只要直接写‘app1_index.html’,Django服务器会在views文件所在的当前层(/app1)中找到templates,从而找到模板'app1_index.html'.

    指定公用的templates路径,所有apps都可以调用,方便快捷。
    app专用的templates不需要指定,这样当要复用这个app的时候,不需要考虑templates路径问题。

    视图views.py

    a. 获取用户请求数据

    request.GET
    request.POST
    request.FILES
    request.path_info       # 当前URL
    request.XXX
    
    - request.body  # 用户数据放在请求body里打包发送
        request.GET.get()
        request.POST
        request.FILES
        
    - request.Meta(...)
        request.method
        request.path_info
        request.COOKIES
        request....
    
    - request.method(PUT,DELETE)
        request.GET/POST会将请求body打包,其他不会
        取body用request.body
    
    - 请求的其他信息
        from django.core.handlers.wsgi import WSGIRequest
        request.environ
        request.environ['HTTP_USER_AGENT']
    

    b. checkbox等多选的内容

    request.POST.getlist()
    

    c. 上传文件

    上传文件时,form标签要做特殊设置

    <form ... enctype="multipart/form-data">
    
    request.POST.get('1.jpg')         # 获取上传文件的文件名
    request.FILES.get('1.jpg')        # 获取上传的文件对象obj
        obj           ->  默认显示name,(内部__repr__函数)
        obj.name
        obj.size
        obj.read()    -> 读取整个上传文件的数据,文件较大时慎用。
        obj.chunks()  ->  一点一点获取数据块
        obj.multiple_chunks(chunk_size=None)   -> 判断文件是否足够大,默认2.5M,大于返回True
            # 可用来判断使用read还是chunks
        obj.content_type   -> 上传文件时的content_type报头,例如(e.g. text/plain or application/pdf).
        obj.charset   -> 编码
    - 获取文件:
        f = open(obj.name,'wb')
        for i in obj.chunks():
            f.write(i)
        f.close()
    

    d. FBV & CBV 两种函数定义方式

    • FBV: function base view 一般函数

        path('index/', views.index),
        
        ./view.py
            def index(request):
                ...
      
    • CBV: class base view 类里的函数

        path('home/', views.Home.as_view()),       # 类名.as_view()
      
        ./view.py
            from django.views import View
            class Home(View):       # 继承View
                def get(self,request)   # 请求GET时执行
      
                def post(self,request)  # 请求POST时执行
      
                # 其他函数
                def dispatch(self,request):  # View父类里负责判断method的函数,自动继承,可重定义
      
                def as_view(self,request):  # 从url转到类中首先执行的方法,默认
      

    两者没有明显优劣,建议:两者都用

    e. 装饰器

    def auth(func):
        def inner(reqeust,*args,**kwargs):
            v = reqeust.COOKIES.get('username111')      # 验证登录状态
            if not v:
                return redirect('/login/')
            return func(reqeust, *args,**kwargs)
        return inner
    
    • FBV装饰器:

        @auth
        def index(request):
            ...
      
    • CBV装饰器:

        from django import views
        from django.utils.decorators import method_decorator
      
        @method_decorator(auth,name='dispatch')   # 装饰所有请求装饰,dispatch,与在dispatch函数前加装饰效果一致
        class Order(views.View):
      
            # @method_decorator(auth)   # 仅装饰get
            def get(self,reqeust):
                v = reqeust.COOKIES.get('username111')
                return render(reqeust,'index.html',{'current_user': v})
      
            def post(self,reqeust):
                v = reqeust.COOKIES.get('username111')
                return render(reqeust,'index.html',{'current_user': v})
      

    模板html

    a.母版

    访问子板时引用母版,并替换母版的同名block块,然后渲染

    • 母板:

        {% block title %} {% endblock %}    # 可放置在任意位置
      
    • 子板:

        {% extends "base.html" %}   # 开头声明母版路径
        {% block title %}
            ...
        {% endblock %}
      

    写自己的css和js时,也要封装成分别的css和js的block块

    b.小模块导入

    将重复的标签块封装成小模块再导入

    {% include 'tag.html' %}    # 可重复导入
    

    c.模板函数 |

    {{ item.event_start|date:"Y-m-d H:i:s"}}
    {{ bio|truncatewords:"30" }}            # 变量前30个字符,用于中文不行
    {{ content |slice:"30" }}          # 变量前30个字符,可用于中文
    {{ my_list|first|upper }}
    {{ name|lower }}
    

    d.自定义函数

    • simple_tag

        <1> app下创建templatetags目录     # 不可改名
      
        <2> 创建任意xxxx.py文件
      
        <3> 在.py文件内创建template对象 register      # 不可改名
            from django import template
            register = template.Library()
      
        <4> 用simple_tag装饰.py内的函数
            @register.simple_tag
            def func1(a1,a2,a3....)      # 可传任意参数
                return "asdfasd"
      
        <5> 在settings中注册APP
      
        <6> 在html顶部引用函数(文件名)
            {% load xxoo %} 
      
        <7> 使用函数
            {% func1 arg1 arg2 %}       # 空格不影响,用{% %}
      
        - 缺点:
            不能作为if条件
        - 优点:
            参数任意
      
    • filter

        <1><2><3><5><6>同上
      
        <4> 用filter装饰.py内的函数
            @register.filter
            def func2(a1,a2)            # 只能最多两个参数
                return "asdfasd"
      
        <7> 使用函数
            {{ 'arg1'|func2:'arg2' }}       # 中间不能加空格,用{{|}}
      
        - 缺点:
            最多两个参数,不能加空格
            要使用多个参数需要将参数传入同一个形参,在函数内部实现分离
        - 优点:
            能作为if条件
            {% if arg1|func2:arg2 %}
            {% end if %}
  • 相关阅读:
    javascript 对象只读
    异步IO
    模板
    Web框架
    WSGI接口
    web开发发展历程
    python函数中的参数类型
    学习网址
    python inspect模块
    详解python的装饰器decorator
  • 原文地址:https://www.cnblogs.com/JeromeLong/p/13252356.html
Copyright © 2011-2022 走看看