ルーティング層003 Djangoフレームワーク

ルーティング層(urls.py)

これは、ルーティング層と呼ばれるDjangoのurls.pyでルーティングファイルを参照します

されたルーティング層アドレスとビュー機能間のユーザマッピングによって要求されたウェブサイトが辞書に例えている場合は、そのディレクトリの数よりも私たちのルーティング(urls.py)は辞書があり、Djangoはurls.pyのデフォルトのファイルにルーティングされます次の図の:

第二に、簡単なルーティング設定

# urls.py路由配置文件
from Django.conf.urls import url

# 有一条条映射关系组成的urlpatterns这个列表称之为路由表
urlpatterns = [
    url(regex,view,kwargs=None,name=None),
    #url本质就是一个函数
]

ファンクション・キー・パラメータは、URLを導入しました:

  • 正規表現:パスのURLアドレス部分にアクセスするためのクライアントを一致させるために使用する正規表現
    • 例えば:URLアドレスは、http://127.0.0.1:8000/index/、正規表現は、インデックスの一部と一致するように/
  • ビュー:通常URLは、ビジネスロジックを処理するためにビュー対応する機能であります
  • kwargsから:少し(使用有名なグループ化を参照してください)
  • 名前:少し(逆引き参照の使用を参照してください)

ケース次のとおりです。

# urls.py文件

from django.conf.urls import url
from django.contrib import admin
from app01 import views # 导入视图函数模块views.py

urlpatterns = [
    url(r'^admin/',admin.site.urls),# 这里是新建一个django项目默认自带的,不用管它
    
    url(r'^index/$',views.index),#这是新增的一条地址与视图函数的对应关系
]
# views.py视图函数文件

from django.shortcuts import render 
from django.shortcuts import redirect
from django.shortcuts import HttpResponse # 导入HttpResponse,用来生成响应信息,就是直接可以返回字符串,将字符串处理过后响应给客户端

def index(request):
    return HttpResponse('这是index.page')

次のようにテストは以下のとおりです。

# 启动服务端方式一:命令行
-->:python manage.py runserver 8001 # 这里启动的时候,可以指定端口号:8001,默认为8000
在浏览器中输入http://127.0.0.1:8001/index/ 就会看到‘我是index.page’    
    
    
# 启动服务端方式二:直接在pycharm窗口中启动
-->:这里要提前在下图中进行配置:

pycharmウィンドウ:以下スタートDjangoプロジェクトサーバ側のメソッド:

2.1 注意一

私たちは自分のブラウザに入力します。http://127.0.0.1:8001/index/を、マッチが成功したら、Djangoは、正規表現トップダウンの試合でルーティングテーブルへのパスインデックス/(urls.pyファイル)の一部を開催します、直ちにビュー機能に対応するパスが実行される、上記項目にuelspatternsルーティングテーブル(urls.pyファイル)であるurl('^index/$',views.index)-----指数関数は、ファイルビューviews.pyの関数です。

2.2 注意二

私たちは、ブラウザに入力されたときにします。http://127.0.0.1:8001/index,Django指数も正規表現に一致していないように見える、正規表現と一致するように、上から下へのルーティングテーブルへのパスの一部を開催します式(R「^インデックス/ $」/で終わる必要があります一致、それは成功率に一致させなければならない)が、実際には、我々は広口次のような理由から、「私はindexpageだ」を参照するには、ブラウザにまだあります。

コンフィギュレーションファイルでのパラメータAPPEND_SLASHのsettings.pyているリンクされたパラメータがTrue / Falseのどの値を:

  • 真APPEND_SLASH =は、(コンフィギュレーションはコンフィギュレーションファイル、デフォルト値はTrueでない場合)、ユーザによって要求されたアドレスのパス部分のURLは、例えば、アドレス要求URL、末尾に/でない場合ます。http://127.0.0.1:8001 /インデックスは、Djangoはルーティングテーブルインデックス正規表現マッチングの一致が失敗した発見され、アドレスの部分を保持する、Djangoはまだマッチしていない、ルーティングテーブルに一致するようにパス/(インデックス/)の後に追加されます//127.0.0.1:8001/index/アドレスフォールドバック要求:マッチが成功した場合、それはブラウザにリダイレクトメッセージが返され、パスが見つからない戻ってくる、ブラウザが-HTTPを再する必要があります。
  • ときAPPEND_SLASH = Falseを、それは追加の操作を行うことはありません、上記の処理が行われていないが、試合のURLの一部であるパスは、パス強度が見つからない返しすぐに失敗します

第三に、ルーティングパケット

パケット、なぜそれべきパケットとは何ですか?

例えば、我々は、ブログシステムを開発し、我々は、物品のIDに基づいて、特定の記事を参照してくださいする必要がある場合ブラウザは、使用可能なリクエストを送信するときに、フィールドを指定するパラメータ(記事のID番号)を渡す必要があるのHttp://127.0.0.1:8001 /物品/ ID = 3、パラメータができ、また、直接パスへのHttp :? //127.0.0.1:8001/article/3/

Djangoは、正規表現のグループ化機能を使用してロードキング、から直接パラメータのための方法を取得する必要があり、2つのグループに分けます:未知の、有名なグループのグループ化

3.1匿名グループ

# urls.py文件

from django.conf.urls import url
from django.contrib import admin
from app01 import views # 添加app001应用中的views视图函数文件

urlpatterns = [
    url(r'^admin',admin.site.urls),
    
    # 下面的正则表达式会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以位置参数的形式传给视图函数,有几个分组就传几个位置参数
    url(r'aritcle/(\d+)/$',view.article),#(\d+)代表匹配数字1-无穷个
]
# views.py视图文件

from django.shortcuts import render
from django.shortcuts import HttpResponse

# 需要额外增加一个形参用于接收传递过来的分组数据
def article(request,article_id):
    return HttpResponse('id为 %s 的文章内容....' %article_id)
# 测试
python.manage.py runserver 8001 
在浏览器输入:http: //127.0.0.1:8001/article/3 会看到:id为3的文章内容....

3.2有名なグループ化

# urls.py文件
from django.conf.urls import url
from django.contrib import admin
from app01 import views # 添加app001应用中的views视图函数文件

urlpatterns = [
    url(r'^admin',admin.site.urls),
    
    # 下面的正则表达式会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以关键字参数(article_id=..)的形式传给视图函数,有几个分组就传几个关键字参数
    url(r'aritcle/(?P<article_id>\d+)/$',view.article),#(\d+)代表匹配数字1-无穷个
]
# views.py视图文件

from django.shortcuts import render
from django.shortcuts import HttpResponse

# 需要额外增加一个形参用于接收传递过来的分组数据
def article(request,article_id):
    return HttpResponse('id为 %s 的文章内容....' %article_id)
# 测试
python.manage.py runserver 8001 
在浏览器输入:http: //127.0.0.1:8001/article/3 会看到:id为3的文章内容....

3.3と有名な匿名のグループ化グループ化の違い

未知のパケットと知られているパケットがパスパラメータのために取得し、ビューに渡され、次のように、違いは次のとおりです。

  1. パケットは、ビュー機能に対応する未知の位置パラメータの形式で送信され、この時点で未知のルーティングテーブル内のレギュラー(urlpatterns)におけるいくつかのパケットがある場合、ビューに対応する関数は、にいくつかの位置パラメータが存在すべきです上記の例では、受信した、唯一の未知のパケット3は、伝達関数を表示することである(views.article(リクエスト、3「」))
  2. パケットの既知の形態が対応するキーワードパラメータに転送される定期パケット(urlpatterns)で知られているいくつかは、ルーティングテーブルに存在し、対応するビュー機能が** kwargsから使用することができる場合に機能を表示パラメータを収集するために直接キーワードパラメータの形式で書くことができる、上記の例でありますviews.article(request,article_id='3')

注意:パケットとして知られても、無名のグループとが混在していません

第四に、ルートの配布

Djangoプロジェクトの増加機能により、アプリはより多くのアプリケーションになり、ルートはより多くの、各アプリは、独自のルートを持つことになりますでしょう、ルーティングテーブル内のすべてのルートを再訪すると、構造は、プロジェクトの維持管理が容易な、明確ではないではないので、我々が引き渡さ自分のルーティングを管理するためのアプリを所有する必要がつながり、その後、配布を行うために、ルーティングテーブルを合計します、次のように、具体的な実践は、以下のとおりです。

4.1 2つのアプリを作成します

# 新建项目mysite1---此处用命令行命令创建
# 切换到存储项目的目录下
django-admin startproject mysite1

# 切换到新建的项目下
# 创建两个app项目(app01和app02)
python3 startapp app01
python3 startapp app02

以下の3点という、ここで注意してください:

  1. 私は、Djangoのプロジェクトを作成するには、コマンドラインを使用し、手動で独自の作成する必要があるテンプレートを使用する必要性を保存するための.htmlファイルフォルダを
  2. そしてへの設定テンプレートの設定: 'DIRS':[os.path.join( BASE_DIR、 'テンプレート')]
  3. 設定ではINSTALLED_APPSは「app01」「app02」に配置されています

4.2手動でルーティングurls.pyにアプリストア内に作成

urls.pyルーティング・テーブル・ファイル1. app01の下で

from django.conf.urls import url
# 导入app01 的views
from app01 import views

urlpatterns = [
    url(r'^index/$',views.index),
]

app01の下にviews.pyビュー機能ファイル

from django.shortcuts import render
from django.shortcuts import HttpResponse

def index(request):
    return HttpResponse('我是app01下的index页面。。。。。')

2. app02 urls.pyルーティング・テーブル・ファイル

from django.conf.urls import url

# 导入app02 的views
from app02 import views

urlpatterns = [
    url(r'^index/$',views.index),
]

app02の下にviews.pyビュー機能ファイル

from django.shortcuts import render
from django.shortcuts import HttpResponse

def index(request):
    return HttpResponse('我是app02下的index页面。。。。。')

ルーティングテーブル4.3合計mysite1フォルダurls.py

from django.conf.urls import url,include
from django.contrib import admin

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

    # 因为功能太多,所以在总的路由表中,做路由分发,分发给各个app功能应用
    # 新增的两条路由,注意不能以$结尾
    # include函数就是做分发操作的,当浏览器输入http://127.0.0.1:8001/app01/index时
    # 会先进入到总路由表中进行匹配,正则表达式r'^app01/'会先匹配成功路径app01/
    # 然后include功能函数就会去app01下的urls.py中继续匹配剩余的路径部分
    url(r'app01/',include('app01.urls')),
    url(r'app02/',include('app02.urls'))
]

テスト:

# 先启动项目server端---命令行式:python manage.py runserver 8001
1.在浏览器中输入:Http://127.0.0.1:8001/app01/index/ 
  会看到我是app01下的index页面。。。

2.在浏览器中输入:Http://127.0.0.1:8001/app02/index/ 
  会看到我是app02下的index页面。。。

第五に、逆解析

質問:多くの場所でのプロジェクトは、パスが変更された後、パスを変更するために使用されている場合は、ソフトウェア開発の初期には、デザインのパスのURLアドレスは完璧ではないかもしれないが、後者の必要性は、それがすべての使用は、パスを変更していることを意味し、調整することができます修正する必要があり、これは非常に面倒な作業です。

解決策: URL(正規表現、ビュー、kwargsから=書き込みされるとなし、名前=なし)を、 URLアドレスエイリアスのパス部分のパラメータ名で、プロジェクトがこのパスの別名を介して取得することができます。どんなにの将来パスに場所を取るどのような変更エイリアスとパスは常に一貫しています。

上述したプロセスを介して取得したそのような経路は、逆DNSエイリアスと呼ばれている:すなわち、逆の経路は、このアドレスにアクセスするために、文字列の一連によって解決されます

ケース:ログイン成功のジャンプの後のページのindex.htmlへ

# urls.py路由文件中

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/',admin.site.urls),
    
    # login/别名的为login_page
    url(r'^login/$',views.login,name='login_page'),
    
    # index/别名的为index_page
    url(r'^index/$',views.index,name='index_page'),
]
# views.py视图函数文件中

from django.shortcuts import render
from django.shortcuts import reverse
from django.shortcuts import redirect
from django.shortcuts import HttpResponse

def login(request):
    if request.method == 'GET':
        # 当为浏览器为get请求时,返回login.html页面,
        # 页面中{% url'login_page' %}会被反向解析成路径:/login/
        return render(request,'login.html')

    # 当浏览器为post请求时,可以从request.POST中取出请求体数据
    name = request.POST.get('name')
    pwd = request.POST.get('pwd')
    if name == 'cecilia' and pwd == '123':

        # reverse会将别名index_page反向解析为路径/index/
        url = reverse('index_page')
        # 重定向到/index/
        return redirect(url)
    
    else:
        return HttpResponse('用户名密码错误!')

   
def index(request):
    return render(request,'index.html')
# login.html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<!--login_page必须要加引号-->
    <form action="{% url 'login_page' %}" method="post">
        {% csrf_token %} <!--强调这一行必须要加,后续会说明-->
        <p>用户名:<input type="text" name="name"></p>
        <p>密码:<input type="password" name="pwd"></p>
        <p>提交:<input type="submit" value="提交"></p>
    </form>
</body>
</html>
# index.html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h3>我是index页面</h3>
</body>
</html>

テスト:

# 先启动django项目server端----命令行 
python manage.py runserver 8001

1. 在浏览器输入:Http://127.0.0.1:8001/login 
   # 会看到登录页面,输入正确的用户名密码会跳转到index.html
2.当我们修改路由表中匹配路径的正则表达式时,程序其他部分都不用修改

要約:

在views.py视图函数文件中,反向解析的使用:
    url = reverse('index_page')
在login.html文件中,反向解析的使用
    {% url 'login_page'%}

読み取り:パスの方向は、パケット解析を用いて、存在する場合

# urls.py路由文件

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/',admin.site.urls),
    url(r'^article/(\d+)/$',view.article,name='article_page'),#无名分组
    url(r'^user/(?p<uid>\d+)/$',view.article,name='user_page'),#有名分组
]
# 1. 针对无名分组,比如我们要反向解析处:/article/1/这种路径,写法如下
在views.py中,反向解析的使用
url =  reverse('article_page',args=(1,))
在模板login.html文件中,反向解析的使用
{% url 'article_page' 1 %}


# 2.针对有名分组,比如我们要反向解析出:/user/1 这种路径,写法如下
在view.py中,反向解析的使用
方式一: url =  reverse('article_page',args=(1,))
方式二: url =  reverse('user_page',kwargs={'uid':1})
在模板login.html文件中,反向解析的使用
方式一:{% url 'article_page' 1 %}
方式二:{% url 'user_page' uid=1 %}


总结:无名分组和有名分组的反向解析,只要记一种就行了。

第六に、名前空間

私たちのプロジェクトは、複数のアプリケーションを作成するには、各アプリの下で重複エイリアスがある場合、以下のように、それは、解析時にカバーが発生返されます、エイリアスパスの試合でプレーしているとき

6.1 2つのアプリを作成します

# 新建项目mysite2---此处用命令行命令创建
# 切换到存储项目的目录下
django-admin startproject mysite2

# 切换到新建的项目下
# 创建两个app项目(app01和app02)
python3 startapp app01
python3 startapp app02

以下の3点という、ここで注意してください:

  1. 私は、Djangoのプロジェクトを作成するには、コマンドラインを使用し、手動で独自の作成する必要があるテンプレートを使用する必要性を保存するための.htmlファイルフォルダを
  2. そしてへの設定テンプレートの設定: 'DIRS':[os.path.join( BASE_DIR、 'テンプレート')]
  3. 設定ではINSTALLED_APPSは「app01」「app02」に配置されています

6.2手動でルーティングurls.pyにアプリストア内に作成

urls.pyルーティング・テーブル・ファイル1. app01の下で

from django.conf.urls import url
# 导入app01 的views
from app01 import views

urlpatterns = [
    # 为匹配的路径app01/index/起别名’index_page‘
    url(r'^index/$',views.index,name='index_page'),
]

2.app02下urls.pyルーティングファイル

from django.conf.urls import url
# 导入app02 的views
from app02 import views

urlpatterns = [
    # 为匹配的路径app02/index/起别名’index_page‘,与app01中的别名相同
    url(r'^index/$',views.index,name='index_page'),
]

各アプリの機能を考慮して調製6.3 views.py

ビュー機能CKSでは別名「index_pageは」逆解析を行います

ファイル1. app01でviews.pyビュー機能

from django.shortcuts import reverse
from django.shortcuts import render
from django.shortcuts import HttpResponse

def index(request):
    url = reverse('index_page')
    return HttpResponse('我是app01下的index页面。。。,反向解析结果为%s' %url)

app02の下にviews.pyビュー機能ファイル

from django.shortcuts import reverse
from django.shortcuts import render
from django.shortcuts import HttpResponse

def index(request):
    url = reverse('index_page')
    return HttpResponse('我是app02下的index页面。。。,反向解析结果为%s' %url)

ルーティングテーブル6.4合計mysite2フォルダurls.py

from django.conf.urls import url,include
from django.contrib import admin

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

    # 因为功能太多,所以在总的路由表中,做路由分发,分发给各个app功能应用
    # 新增的两条路由,注意不能以$结尾
    # include函数就是做分发操作的,当浏览器输入http://127.0.0.1:8001/app01/index时
    # 会先进入到总路由表中进行匹配,正则表达式r'^app01/'会先匹配成功路径app01/
    # 然后include功能函数就会去app01下的urls.py中继续匹配剩余的路径部分
    url(r'app01/',include('app01.urls')),
    url(r'app02/',include('app02.urls'))
]

6.5テスト:(カバレッジの問題)

# 先启动项目server端---命令行式:python manage.py runserver 8001
1.在浏览器中输入:Http://127.0.0.1:8001/app01/index/ 
  会看到我是app02下的index页面。。。,反向解析的结果为/app02/index/

2.在浏览器中输入:Http://127.0.0.1:8001/app02/index/ 
  会看到我是app02下的index页面。。。,反向解析的结果为/app02/index/

テストでは、私たちが発見したブラウザ上の入力として:のHttp://127.0.0.1:8001/app01/index/か

Http:別名「index_page」方向について//127.0.0.1:8001/app02/index/は、分析app01エイリアスをカバーする分析/ app02 /インデックス/、の結果です。

6.6ソリューション

ソリューション:お互いに、同じエイリアスを使用しないことです、あなたが同じエイリアスを使用したい場合、それはジャンゴでの名前空間の概念を使用する必要があり、異なる名前空間にエイリアス、そうであっても、複製、ありません紛争、具体的には、以下の

  1. 合計(mysite2下)urls.pyルートの配布を行うことで、指定した名前空間

    from django.conf.urls import url,include
    from django.contrib import admin
    
    # 总路由表
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
    
        # 传给include功能一个元组,元组的第一个值是路由分发的地址
        # 第二个值是我们为名称空间起的名字
        url(r'^app01/',include(('app01.urls','app01'))),
        url(r'^app02/',include(('app02.urls','app02')))
    ]
  2. Views.py異なる名前空間のための機能を考慮して変更し、各アプリの下に、それぞれ匿名「index_page」逆解析を行います

    app01下view.pyビュー機能

    from django.shortcuts import reverse
    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    
    def index(request):
        # 解析的是名称空间app01下的别名’index_page‘
        url = reverse('app01:ndex_page')
        return HttpResponse('我是app01下的index页面。。。,反向解析结果为%s' %url)

    app02下view.pyビュー機能

    from django.shortcuts import reverse
    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    
    def index(request):
        # 解析的是app02下的名称空间的别名’index_page‘
        url = reverse('app02:index_page')
        return HttpResponse('我是app02下的index页面。。。,反向解析结果为%s' %url)

6.7テスト(テスト問題を解決するために)

python manage.py runserver 8001

ブラウザに入力します。http://127.0.0.1:8001 / app01 /インデックス/ 解析の逆の結果/ app01 /インデックス/

ブラウザは、次のように入力しますHttp://127.0.0.1:8001/app02/index/ 逆解析の結果である/ app02 /インデックス/

6.8 +補足概要

1. 在视图函数中基于名称空间的反向解析,用法如下
url = reverse('名称空间的名字:待解析的别名')

2.在模板里基于名称空间的反向解析,用法如下
{% url '名称空间的名字:待解析的别名'%}

七、Django2.0バージョンre_pathとパス

7.1 re_path

最初の引数に渡されたURLはDjango 1.0、などは、正規表現であるre_pathでDjangoの2.0

from django.urls import re_path # django 2.0 中的re_path
from django.conf.urls import url # 在django2.0中同样可以导入1.0中的url

urlpatterns = [
    # 用法完全一致
    url(r'^app01/',include(('app01.urls','app01'))),
    re_path(r'^app02/',include(('app02.urls','app02'))),
]

7.2パス

次のようにデータ型変換や冗長正規表現、:Djangoの2.0で解決する新しいパス機能があり、

# urls.py 文件

from django.urls import re+path
from app01 import views

urlpatterns = [
    # 问题一:数据类型转换
    # 正则表达式会将请求路径中的年份匹配成功然后以str类型传递函数year_archive
    # 在函数year_archive中如果想要以int类型的格式处理年份,则必须进行数据类型转换
    
    re_path(r'^articles/(?P<year>[0-9]{4})/$',views.year_archive),
    
   
    # 问题二:正则表达式冗余
    # 下述三个路由中匹配article_id 采用了同样的正则表达式,重发编写了三遍,存在冗余问题,并且极不容易管理,因为以但articles_id规则需要改变,则必须同时修改三处的代码
    re_path(r'^articles/(?P<article_id>[a-zA-z0-9]+)/detail/$',view,detail_view),
    re_path(r'^articles/(?P<article_id>[a-zA-z0-9]+)/edit/$',view,edit_view),
    re_path(r'^articles/(?P<article_id>[a-zA-z0-9]+)/delete/$',view,delete_view),
]
# views.py视图文件
from django.shortcuts import render,HttpResponse

def year_archive(request,year):
    print(year,type(year))
    return HttpResponse('year_archive page')

def detail_view(request,article_id):
    print(article_id,type(article_id))
    return HttpResponse('detail_view page')

def edit_view(request,article_id):
    print(article_id,type(article_id))
    return HttpResponse('edit_view page')

def delete_view(request,article_id):
    print(article_id,type(article_id))
    return HttpResponse('delete_view page')

どのようにパスがこの2つの問題を解決するためにdjango2.0?例を参照してください。

# urls.py路由文件

from django.urls import re+path
from app01 import views

urlpatterns = [
    # 问题一的结局方案
    path('^articles/<int:year>/',views.year_archive),
    # <int:year>相当于一个有名分组,其中int是django提供的转换器
    # 相当于正则表达式,专门用于匹配数字类型
    # 而year则是我们为有名分组名的名,并且int会将匹配成功后的结果转换位整型后按照格式(year=整型值),传给函数year_archive
    
   
    # 问题二的解决办法
    # 用一个int转换器可以替代对出正则表达式
    path('^articles/<int:article_id>/detail/',view,detail_view),
    path('^articles/<int:article_id>edit/',view,edit_view),
    path('^articles/<int:article_id>delete/',view,delete_view),
]

彼は強調しました:

  1. URLは異なるre_pathパスが1.0であるとか、パスの最初のパラメータは、正規表現ではなく、パスの正確な一致、最初のパラメータは追加しないマッチング文字の前文で述べたものと同じですスラッシュ
  2. アングルブラケット(<>)は、公知のパケットに対応し、URL値からキャプチャ
  3. コンバータ使用INT <>このような使用<名前整数>のように、型コンバータ(変換タイプ)を含んでもよいです。変換はもちろん、/文字を含む任意の文字列と一致しません場合

ジャンゴ:デフォルトサポート5コンバータ(パスコンバータ)

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

おすすめ

転載: www.cnblogs.com/XuChengNotes/p/11722941.html