zoukankan      html  css  js  c++  java
  • Django

    一、django 静态文件配置

    /first_pro/settings.py

    STATIC_URL = '/static/'  # 这个别名对应的实际路径。浏览器就得输入static
    
    # 配置静态文件路径 STATICFILES_DIRS
    = [ os.path.join(BASE_DIR,'statics'), ]

    在项目中新建一个statics文件夹,所有的静态文件都存入在这个目录中;

    如上文所示,配置完静态文件路径之后,浏览器访问到了http://127.0.0.1:8000/static/jquery-3.2.1.js

    1.实现一个小程序,输入网址,返回时间,点击时间变色。

    views.py

    from django.shortcuts import render,HttpResponse
    # HttpResponse:响应对象,写字符串,对应的是响应体(响应头和响应首行已经被django的wsgi处理了)
    # Create your views here.
    
    def timer(request):
        import datetime
    
        data = (datetime.datetime.now()).strftime("%y-%m-%d %X")
    
        return render(request,"timer.html",{"timer":data})
        # render():渲染一个方法,找到文件,读文件,返回

    render方法就是去渲染一个方法,帮我们去找templates下面的文件,读出数据返回;同时它还把这个timer变量嵌套到了timer.html这个页面中了

    {{timer}} ,{ { } } 就是一种特殊语法,把视图函数里边的变量传到html页面中

    templates/timer.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    {#    <style>#}
    {#        h4{#}
    {#            color: red;#}
    {#        }#}
    {#    </style>#}
    
        <script src="/static/jquery-3.3.1.js"></script>   {# 客户端浏览器执行的时候它找不到这个文件,得配置一个static路径 #}
        <link rel="stylesheet" href="/static/app01/timer.css">
    </head>
    <body>
        {#  {{ }}:  默认格式#}
        <h4>日期时间:{{ timer }}</h4>
        <script src="/static/app01/timer.js                                                                                                                            "></script>
    
    {#    <script type="text/javascript">#}
    {#        $("h4").click(function () {#}
    {#            $(this).css('color','green')#}
    {#        })#}
    {#    </script>#}
    
    </body>
    </html>

    statics/app01/ timer.css

    h4{
                color: red;
            }

    statics/app01/ timer.js

    $("h4").click(function () {
                $(this).css('color','green')
            })

    效果

    点击时间后:

     整个流程:用户输入http://127.0.0.1:8000/timer/交给URL控制器(控制行为),匹配到就执行timer视图函数(一旦匹配成功,path这个函数方法帮你去调这个匹配到的函数,调的时候就会给你传一个request参数,所有的请求信息数据都封装在了request里边),这个视图函数在app01里的views里边找到timer方法(timer方法做逻辑处理);取出来一个叫timer(之前我们是open这个文件然后再返回,现在通过一个render方法把这所有的事情都做了。)

    二、简单得路由配置

    URL配置(URLconf) 就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行。

     re_path是1.0版本的,path是2.0版本的,2.0既支持1.0的又支持它自己特殊的语法

    import re
    
    re.search(匹配规则,待匹配项);^是以什么开头,$是以什么结尾;
    from django.contrib import admin
    from django.urls import path,re_path
    from app01 import views
    
    urlpatterns = [
    路由配置:  路径---------------->视图函数
        re_path(r'^articles/2003/$',views.special_case_2003),
        re_path(r'^articles/([0-9]{4})/$',views.year_archive),
        # year_archive(request,‘2009’)  ()加了一个组,需将组的内容当做参数传入函数中
    
        # re_path(r'^articles/([0-9]{4})/([0-9]{2})/$',views.month_archive),
        # 关键字传参,固定合适?P<name>
        # month_archive(y=2009,m=08),视图函数中必须传入的参数是y和m
        re_path(r'^articles/(?P<y>[0-9]{4})/(?P<m>[0-9]{2})/$',views.month_archive),
        re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',views.article_detail),
    ]
    from django.shortcuts import render,HttpResponse
    # HttpResponse:响应对象,写字符串,对应的是响应体(响应头和响应首行已经被django的wsgi处理了)
    #
    你想在这个页面中看什么内容,就在HttpResponse里边写什么内容就可以了
    def special_case_2003(request):
    
        return HttpResponse('special_case_2003')
    
    
    def year_archive(request,y):
    
        return HttpResponse(y)
    
    
    def month_archive(request,y,m):
    
        return HttpResponse(y+'-'+m)
    
    
    def article_detail(request,y,m,d):
    
        return HttpResponse(y+'-'+m+'-'+d)

     

    注意:

    • 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
    • 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles
    • 每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义

    三、有名分组

        上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。

        在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。

        下面是以上URLconf 使用命名组的重写:

    from django.urls import path,re_path
    
    from app01 import views
    
    urlpatterns = [
         # 关键字传参,固定模式?P<name>
        re_path(r'^articles/(?P<year>[0-9]{4})/$',views.year_archive), #year_archive(request,year=2009)
        # month_archive(year=2009,month=08),视图函数中必须传入的参数是y和m
        re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$',views.month_archive),
        re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',views.article_detail),
        re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), #(request,year=2018,month=08,day=08)
    ]
    from django.shortcuts import render,HttpResponse
    
    def year_archive(request,year):
    
        return HttpResponse(year)
    
    
    def month_archive(request,month,year): #把它位置捣乱,就乱了;可以给每个组起个名字固定住;一定要按关键字来,是那个名字;这里形参必须是month 和 year,不能写成m或者y
    
        return HttpResponse(year+'-'+month)
    
    def article_detail(request,year,month,day):
    
        return HttpResponse(year+"-"+month+"-"+day)

    这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。例如:

    /articles/2005/03/ 请求将调用views.month_archive(request, year='2005', month='03')函数,而不是views.month_archive(request, '2005', '03')。
    /articles/2003/03/03/ 请求将调用函数views.article_detail(request, year='2003', month='03', day='03')。

    在实际应用中,这意味你的URLconf 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价;

    四、路由分发

        全局不应该写url,它应做分发。

        把全局的urls.py复制到app01的应用里边一份,然后把全局的path那部分给删掉。全局里边(也就是first_pro里边的urls)的针对app01的re_path给删掉。

    appo1/urls.py(app01里边的)

    from django.contrib import admin
    from django.urls import path, re_path
    
    from app01 import views
    
    urlpatterns = [
        # 路由配置:  路径---------------->视图函数
        re_path(r'^articles/2003/$',views.special_case_2003,name='s_c_2003'),
        re_path(r'^articles/([0-9]{4})/$',views.year_archive,name='y_a'),
        # year_archive(request,‘2009’)  ()加了一个组,需将组的内容当做参数传入函数中
    
        # re_path(r'^articles/([0-9]{4})/([0-9]{2})/$',views.month_archive),
        # 关键字传参,固定合适?P<name>
        # month_archive(y=2009,m=08),视图函数中必须传入的参数是y和m
        re_path(r'^articles/(?P<y>[0-9]{4})/(?P<m>[0-9]{2})/$',views.month_archive,name='m_a'),
        re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',views.article_detail),
    
        re_path('index/',views.index,name='index')
    ]

    first_pro/urls.py(全局的)

    from django.contrib import admin
    from django.urls import path, re_path, include
    
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('timer/', views.timer), # timer(request):调用的时候自动传入request
        path('login.html/', views.login),
        # 路由分发
        # 导入include
        # 分发 每个url单独写到自己的app里边去,在全局做分发就可以了,实现了解耦;
        # 先找到app01,然后剩下的到app01.urls中去找
        # re_path(r'app01/',include("app01.urls")), #如浏览器中输入,前面就必须加app01了http://127.0.0.1:8000/app01/articles/2003/04
        # 如何去掉链接中的app01
        # re_path(r"^",include("app01.urls "))  #浏览器中就可以不写app01了

    app01 views.py

    from django.shortcuts import render,HttpResponse
    
    def timer(request):
        import datetime
    
        data = (datetime.datetime.now()).strftime("%y-%m-%d %X")
    
        return render(request,"timer.html",{"timer":data})
    
    def login(request):
    
        return render(request, "login.html")
    
    def special_case_2003(request):
        
        return HttpResponse("special_case_2003")
    
    def year_archive(request,year):
    
        return HttpResponse(year)
    
    def month_archive(request,m,y):
    
        return HttpResponse(y+"-"+m)
    
    def article_detail(request,year,month,day):
    
        return HttpResponse(year+"-"+month+"-"+day)
    
    def index(request):
    
        return HttpResponse('app01:index')

     示例:

     

    五、反向解析

    在使用Django 项目时,一个常见的需求是获得URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。人们强烈希望不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。

    在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:

    • 在模板中:使用url 模板标签。
    • 在Python 代码中:使用from django.urls import reverse()函数

    模板语法只有2个:一个是{{}},另外一个就是{% %}

    在模板中

    urls.py

    from django.urls import path,re_path,include
    
    from app01 import views
    
    urlpatterns = [
        path('login.html/',views.login,name='Log'),
    
    ]
    # 反向解析:由于login页面提交的时候action提交的页面是写死的,当我们在url中修改(如login/改为login.html/),
    # 当我们再次提交页面的时候,写死的页面在url中就会找不到了,需要使用{%%}模板

    views.py

    def login(request):
    
        # print(request.method)
        # 登陆是GET请求,提交验证是POST请求
        if request.method == "GET":
            return render(request,"login.html")
        else:
            # print(request.GET)
            # print(request.POST)
            if request.POST.get('user') == 'mm' and request.POST.get('pwd') == '123':
                return HttpResponse('登陆成功!')
            else:
                return HttpResponse('用户名或密码错误!')

    login.html<!DOCTYPE html>

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {#    <form action="" method="post">#}
        <!--<form action="http://127.0.0.1:8800/login/" method="post">--> ##如果不加,就默认是当前页面的网址,/login要加,login要跟url路由里边对应好了
        <form action="{% url 'log'%}" method="post">

      
    {#刚刚我们把它写死了;模板语法之一,render在渲染这个html页面的过程中,它会去解析这个html页面,解析到{% url 'log' %}的时候它就反向解析;
    它要去全局里边找一个叫log的name,找到之后取出来渲染之后替换{% url 'log' %}这部分内容,然后再发给客户端的浏览器#}
            用户名:<input type="text" name="user">
            密码:<input type="password" name="pwd">
            <input type="submit">
        </form>
    
    </body>
    </html>

    流程

    如果urlpatterns里边的路径path改为login.html/,其他地方都不需要改动。用户在浏览器中输入http://127.0.0.1:8000/login.html/时,得到的页面,它访问的在视图里边,视图里边再渲染login.html(return render(request,"login.html")),渲染它的过程中在 <form action="{% url 'log' %}" method="post">中取log,拿到 name="log",

    path('login.html/',views.login, name="log"),改完之后把login.html拿到action中。

    提交数据报错:

    解决方法:

    在python中 

    app01/url.py

    from django.contrib import admin
    from django.urls import path,re_path
    from app01 import views
    
    urlpatterns = [
        # 路由配置:  路径---------------->视图函数
        re_path(r'^articles/2003/$',views.special_case_2003,name='s_c_2003'),
        re_path(r'^articles/([0-9]{4})/$',views.year_archive,name='y_a'),
        # year_archive(request,‘2009’)  ()加了一个组,需将组的内容当做参数传入函数中
    
        # re_path(r'^articles/([0-9]{4})/([0-9]{2})/$',views.month_archive),
        # 关键字传参,固定合适?P<name>
        # month_archive(y=2009,m=08),视图函数中必须传入的参数是y和m
        re_path(r'^articles/(?P<y>[0-9]{4})/(?P<m>[0-9]{2})/$',views.month_archive,name='m_a'),
        re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',views.article_detail),
    
        re_path('index/',views.index,name='index')
    ]

    views.py

    from django.shortcuts import render,HttpResponse
    
    # 在python 里面反向解析 不想写死url 在以后会很灵活
    from django.urls import reverse
    def special_case_2003(request):
    
        # 反向解析
        url = reverse('s_c_2003')
        url = reverse('y_a',args=('7777',))
        # app01/articles/([0-9]{4})/ 这种正则的形式,需要传入数值,几个组传入几组规定长度的数
    
        url = reverse('m_a',args=('7777','77',))
    
        print(url)  #先从全局里边找,没有再去局部里边找,有个name="s_c_2003";它写到哪个视图函数下面是无所谓的,它利用的是reverse这个函数
    # /app01/articles/7777/77/
    return HttpResponse("special_case_2003") 

    def year_archive(request,year):

      return HttpResponse(year)

    def month_archive(request,m,y):

      return HttpResponse(y+"-"+m)

    def article_detail(request,year,month,day):

      return HttpResponse(year+"-"+month+"-"+day)

        跟当前访问的路径没有关系,只是给它反向解析了,给我一个别名就可以解析出这个url,它含正则表达式,就可以通过参数来进行匹配替换从而拿到一个固定的url

         注:当命名你的URL 模式时,请确保使用的名称不会与其它应用中名称冲突。如果你的URL 模式叫做comment,而另外一个应用中也有一个同样的名称,当你在模板中使用这个名称的时候不能保证将插入哪个URL。在URL 名称中加上一个前缀,比如应用的名称,将减少冲突的可能。我们建议使用myapp-comment 而不是comment

    六、名称空间

        命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

        由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回
    我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。

     创建应用app02:

    project的urls.py:

    from django.urls import path,re_path,include
    
    urlpatterns = [
        # 为了防止两个应用下面出现相同的名称带来的问题,使用名称空间,使用方法如下("app01.urls","app01")加上了名称空间app01
        # 在元组里边给它加上个名称空间app01、app02,起个房间号,名称空间。
        path('app01/',include(('app01.urls','app01'))), # 右面是名称空间, 命名空间的意义
        path('app02/',include(('app02.urls','app02'))),
    
    ]

    app01.urls:

    from django.urls import path,re_path,include
    from app01 import views
    
    urlpatterns = [
        path('index/', views.index, name='index')
    
    ]

    app02.urls:

    from django.urls import path, re_path, include
    from app02 import views
    
    urlpatterns = [
        path('index/', views.index, name='index')
        
    ] 

    app01.views 

    from django.shortcuts import render,HttpResponse
    from django.urls import reverse
    
    def index(request):
        # 名称空间使用方法:'app01:index'
        return HttpResponse(reverse('app01:index'))

    app02.views 

    from django.shortcuts import render,HttpResponse
    from django.urls import reverse
    
    def index(request):
        # 名称空间使用方法:'app02:index'
        return HttpResponse(reverse('app02:index'))

    七、django2.0版的path

    urlpatterns = [  
        re_path('articles/(?P<year>[0-9]{4})/', year_archive),  
        re_path('article/(?P<article_id>[a-zA-Z0-9]+)/detail/', detail_view),  
        re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/edit/', edit_view),  
        re_path('articles/(?P<article_id>[a-zA-Z0-9]+)/delete/', delete_view),  
    ]

        考虑下这样的两个问题:

        第一个问题,函数 year_archive 中year参数是字符串类型的,因此需要先转化为整数类型的变量值,当然year=int(year) 不会有诸如如TypeError或者ValueError的异常。那么有没有一种方法,在url中,使得这一转化步骤可以由Django自动完成?

        第二个问题,三个路由中article_id都是同样的正则表达式,但是你需要写三遍,当之后article_id规则改变后,需要同时修改三处代码,那么有没有一种方法,只需修改一处即可?

        在Django2.0中,可以使用 path 解决以上的两个问题。

    示例

    简单例子:

    first_prourls

    from django.urls import path
    from app01 import views
    
    urlpatterns = [
        path("articles/<int:year>", views.path_year) #匹配数字,浏览器默认发的是字符串;path_year(request,2001)
        #path("articles/<path:year>", views.path_year) #只要非空就可以了,?不行,?=1get请求时把它作为了分隔匹配的内容了
    ]

    app01views

    from django.shortcuts import render,HttpResponse
    
    def path_year(request,year):
    
        print(year)
        print(type(year))
    
        return HttpResponse('path year...')

    基本规则:

    • 使用尖括号(<>)从url中捕获值。
    • 捕获值中可以包含一个转化器类型(converter type),比如使用 <int:name> 捕获一个整数变量。如果没有转化器,将匹配任何字符串,当然也包括了 / 字符。
    • 无需添加前导斜杠。

    path转化器

    文档原文是Path converters,暂且翻译为转化器。

    Django默认支持以下5个转化器:

    • str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
    • int,匹配正整数,包含0。
    • slug,匹配字母、数字以及横杠、下划线组成的字符串。
    • uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
    • path,匹配任何非空字符串,包含了路径分隔符

    注册自定义转化器

    对于一些复杂或者复用的需要,可以定义自己的转化器。转化器是一个类或接口,它的要求有三点:

    • regex 类属性,字符串类型
    • to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
    • to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。

    新建一个py文件  urlconvert.py

    # -*- coding:utf-8 -*-
    
    # 自定义url转换器
    class MonConvert:
        regex = '[0-9]{2}'
    
        def to_python(self,value):
            return int(value)
    
        def to_url(self,value):    # 反向解析
            return '%04d' % value

    first_prourls(使用register_converter 将其注册到URL配置中)

    from django.urls import path,register_converter
    from app01 import views
    
    from app01.urlconvert import MonConvert
    
    # 注册转换器  注册自定义的转换器
    register_converter(MonConvert,'mm')
    
    urlpatterns = [
        # 自己注册的转换器
        path('articles/<mm:month>/', views.year_archive),
    ]

    views.py

    from django.shortcuts import render,HttpResponse
    
    def year_archive(request,month):
        print(month,type(month))
        return HttpResponse('path month...')

    总结:

    django urls:
    简单配置
    第一站: url 路径匹配
    有名分组
    。。。 按关联字传参 (?P...) () 可传参
    分发:
    多个app
    反向解析
    不想写死url 别名name
    名称空间
    防止名字起重了 配合反向解析使用
    path # django 2.0 的特性
    内部数值不会转换 正则反复使用

     含正则的 反向解析 
    https://www.cnblogs.com/yuanchenqi/articles/7629939.html

  • 相关阅读:
    pip不是内部或外部命令也不是可运行的程序或批处理文件的问题
    动态规划 leetcode 343,279,91 & 639. Decode Ways,62,63,198
    动态规划 70.climbing Stairs ,120,64
    (双指针+链表) leetcode 19. Remove Nth Node from End of List,61. Rotate List,143. Reorder List,234. Palindrome Linked List
    建立链表的虚拟头结点 203 Remove Linked List Element,82,147,148,237
    链表 206 Reverse Linked List, 92,86, 328, 2, 445
    (数组,哈希表) 219.Contains Duplicate(2),217 Contain Duplicate, 220(3)
    重装系统
    java常用IO
    端口
  • 原文地址:https://www.cnblogs.com/mumupa0824/p/10247840.html
Copyright © 2011-2022 走看看