ディレクトリ
Djangoのルーティング層
アクションからのすべての方法
サイトが本に比べた場合、ビュー機能間の要求ルーティングとアドレスのマッピングは、そのルートは以下のチャートでurls.pyのデフォルトの設定では、この本のディレクトリのようなDjangoのルーティングです:
2つの単純なルーティング設定
# urls.py
from django.conf.urls import url
# 由一条条映射关系组成的urlpatterns这个列表称之为路由表
urlpatterns = [
url(regex, view, kwargs=None, name=None), # url本质就是一个函数
]
#函数url关键参数介绍
# regex:正则表达式,用来匹配url地址的路径部分,
# 例如url地址为:http://127.0.0.1:8001/index/,正则表达式要匹配的部分是index/
# view:通常为一个视图函数,用来处理业务逻辑
# kwargs:略(用法详见有名分组)
# name:略(用法详见反向解析)
ケース:
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),
url(r'^index/$',views.index), # 新增一条
]
views.pyファイル
from django.shortcuts import render
from django.shortcuts import HttpResponse # 导入HttpResponse,用来生成响应信息
# 新增视图函数index
def index(request):
return HttpResponse('index page...')
テスト:
python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/index/ 会看到 index page...
注意:
私たちは、ブラウザに入力した:マッチが成功したらhttp://127.0.0.1:8001/index/,Djangoはすぐに、その後、正規表現と一致するルーティングテーブルへのパスインデックス/トップダウンの部分を開催しますその後のビュー機能を実行し、試合を下に続行されません、一致、正規表現、ここで成功している R「^インデックス/ \(」注意II:私たちは、あなたのブラウザに入力します。[http://127.0.0.1 :8001 /インデックス、Djangoのインデックスは、ルーティングテーブル保持部にトップダウンパスが正規表現と一致し、一見しない任意の正規表現の一致が成功した](なし)(R&LT「インデックス^ / \)」一致/で終わらなければならないが、それは)成功の指標と一致しませんが、実際にはまだ次のような理由から、...結果のインデックスページを参照してください。
設定ファイルのsettings.pyでAPPEND_SLASHパラメータがあり、パラメータが2つの値を持っていますTrueまたはFalse
真APPEND_SLASH =(設定は設定ファイルでない場合は、デフォルト値がTrue APPEND_SLASHである)、およびユーザが要求したアドレスのパス部分のURLがない場合は/最後に、例えば、要求されたアドレスがURLでのhttp://127.0。 0.1:8001 /インデックス、Djangoはかかります パスの部分(すなわち、インデックス)ルーティングテーブルには、Djangoがパスの後に追加され、正規表現のマッチが失敗した発見された一致して、試合はそれはパスが見つからない返します。失敗した場合、ルーティングテーブルを一致させるために行くために/(つまり、インデックス/)マッチが成功した場合、それはブラウザにリダイレクトメッセージを返します、ブラウザが再する必要が要求http://127.0.0.1:8001/index/アドレスを送信します。
偽APPEND_SLASH =、上記の処理を行わないときパス部分の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
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 下述正则表达式会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以位置参数的形式传给视图函数,有几个分组就传几个位置参数
url(r'^aritcle/(\d+)/$',views.article),
]
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
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 该正则会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以关键字参数(article_id=匹配成功的数字)的形式传给视图函数,有几个有名分组就会传几个关键字参数
url(r'^aritcle/(?P<article_id>\d+)/$',views.article),
]
views.pyファイル
from django.shortcuts import render
from django.shortcuts import HttpResponse
# 需要额外增加一个形参,形参名必须为article_id
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 的文章内容...
要約:既知および未知のパケットのパケット送信、既知の送信キーパラメータの形でパケットの形で未知のパラメータの位置ことを除いて、パスのパラメータを得るためにパケット、およびビュー自体です。
彼は強調した:未知のグループ化と有名なグループが混在していません
四本のルートの配布
プロジェクトの機能の増加に伴い、アプリはより多くの、より多くのルートになります、各アプリは、独自のルートを持っていますし、ルーティングテーブルへのすべてのルートならば、それは構造的につながることはありません管理が容易で、明確ではないが、私たちは、その後、自分のルーティングを管理するルーティングテーブル内の合計分布を作るためのアプリに引き渡されるべき、具体的には、以下の
1は、2つのアプリを作成します
# 新建项目mystie2
E:\git>django-admin startproject mysite2
# 切换到项目目录下
E:\git>cd mysite2
# 创建app01和app02
E:\git\mysite2>python3 manage.py startapp app01
E:\git\mysite2>python3 manage.py startapp app02
独自のルートを保存するために、各アプリで手動で作成した2 urls.py、次のように
下app01ファイルのurls.py
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页面...')
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页面...')
総urls.pyファイル(mysite2フォルダurls.py)3
from django.conf.urls import url,include
from django.contrib import admin
# 总路由表
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 新增两条路由,注意不能以$结尾
# 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')),
]
テスト:
python manage.py runserver 8001
# 在浏览器输入:http://127.0.0.1:8001/app01/index/ 会看到:我是app01的index页面...
# 在浏览器输入:http://127.0.0.1:8001/app02/index/ 会看到:我是app02的index页面...
ファイブ逆引き参照
ソフトウェア開発の初期には、デザイン・パスのURLアドレスは完璧ではないかもしれないが、後者の必要性を調整することができるプロジェクトは、パスの多くの部分で使用されている場合は、パスが変更されると、それは、パスのすべての使用を変更する必要があることを意味これは非常に複雑な操作です。
溶液は、URL(正規表現、ビュー、kwargsから=書くことときなし、名前=なし)を、 URLアドレスエイリアスのパス部分のパラメータ名で、プロジェクトがこのパスエイリアスを介して取得することができます。経路変更エイリアスと常に一貫後に何があってパス。
逆引き参照の別名として知られるプロセスを通じてパスを取得するために、上記の溶液中
ケース: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),
url(r'^login/$', views.login,name='login_page'), # 路径login/的别名为login_page
url(r'^index/$', views.index,name='index_page'), # 路径index/的别名为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 == 'kevin' and pwd == '123':
url = reverse('index_page') # reverse会将别名'index_page'反向解析成路径:/index/
return redirect(url) # 重定向到/index/
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>
テスト:
python manage.py runserver 8001
# 在浏览器输入:http://127.0.0.1:8001/login/ 会看到登录页面,输入正确的用户名密码会跳转到index.html
# 当我们修改路由表中匹配路径的正则表达式时,程序其余部分均无需修改
要約:
在views.py中,反向解析的使用:
url = reverse('index_page')
在模版login.html文件中,反向解析的使用
{% url 'login_page' %}
参考資料:
パスが使用のパケットがある場合は、解像度を逆:
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^aritcle/(\d+)/$',views.article,name='article_page'), # 无名分组
url(r'^user/(?P<uid>\d+)/$',views.article,name='user_page'), # 有名分组
]
# 1 针对无名分组,比如我们要反向解析出:/aritcle/1/ 这种路径,写法如下
在views.py中,反向解析的使用:
url = reverse('article_page',args=(1,))
在模版login.html文件中,反向解析的使用
{% url 'article_page' 1 %}
# 2 针对有名分组,比如我们要反向解析出:/user/1/ 这种路径,写法如下
在views.py中,反向解析的使用:
url = reverse('user_page',kwargs={'uid':1})
在模版login.html文件中,反向解析的使用
{% url 'user_page' uid=1 %}
六の名前空間
私たちのプロジェクトは、複数のアプリケーションを作成するには、各アプリの下で、別名パスの試合でプレーしているときに、重複するエイリアスがある場合、それは下にカバーする逆解析に表示される
2つのアプリを作成します。1
# 新建项目mystie2
E:\git>django-admin startproject mysite2
# 切换到项目目录下
E:\git>cd mysite2
# 创建app01和app02
E:\git\mysite2>python3 manage.py startapp app01
E:\git\mysite2>python3 manage.py startapp app02
2 urls.pyは、独自のルートを保存するために、各アプリで手動で作成し、パスの別名から一致する
app01下urls.pyファイルを
from django.conf.urls import url
from app01 import views
urlpatterns = [
# 为匹配的路径app01/index/起别名'index_page'
url(r'^index/$',views.index,name='index_page'),
]
app02下urls.pyファイル
from django.conf.urls import url
from app02 import views
urlpatterns = [
# 为匹配的路径app02/index/起别名'index_page',与app01中的别名相同
url(r'^index/$',views.index,name='index_page'),
]
各アプリの下view.pyビュー、別名「index_page」のビュー機能は、分析逆ない3つの書き込み機能
app01下views.pyを
from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import reverse
def index(request):
url=reverse('index_page')
return HttpResponse('app01的index页面,反向解析结果为%s' %url)
app02下にviews.py
from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import reverse
def index(request):
url=reverse('index_page')
return HttpResponse('app02的index页面,反向解析结果为%s' %url)
総urls.pyファイル(mysite2フォルダurls.py)3
from django.conf.urls import url,include
from django.contrib import admin
# 总路由表
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 新增两条路由,注意不能以$结尾
url(r'^app01/', include('app01.urls')),
url(r'^app02/', include('app02.urls')),
]
4、テスト:
python manage.py runserver 8001
テストでは、両方のブラウザ入力に:http://127.0.0.1:8001/app01/index/又は入力http://127.0.0.1:8001/app02/index/別名「index_page」逆ルックアップ結果を得るためにエイリアスの下で分析app01をカバーし、すべて/ app02 /インデックス/、。
この問題を解決する1つの方法は、同じエイリアスを使用しないことです、あなたが同じエイリアスを使用したい場合、それはジャンゴでの名前空間の概念を使用する必要があり、異なる名前空間にエイリアスが、そうであっても、複製します次のように互いに競合しないであろう、特定の慣行である
総urls.pyルート分布は、名前空間を指定する1、
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、各アプリケーションのビューの編集view.py機能、異なる名前空間の別名「index_pageは、」分析リバースん
app01の下にviews.pyを
from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import reverse
def index(request):
url=reverse('app01:index_page') # 解析的是名称空间app01下的别名'index_page'
return HttpResponse('app01的index页面,反向解析结果为%s' %url)
app02下にviews.py
from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.shortcuts import reverse
def index(request):
url=reverse('app02:index_page') # 解析的是名称空间app02下的别名'index_page'
return HttpResponse('app02的index页面,反向解析结果为%s' %url)
3、テスト:
python manage.py runserver 8001
:ブラウザの入力/ / app01 /インデックスされた結果の分析を逆転http://127.0.0.1:8001/app01/index/を
ブラウザ入力のルックアップhttp://127.0.0.1:8001/app02/index/を逆転結果は/ app02 /インデックス/で
要約+サプリメント
1、在视图函数中基于名称空间的反向解析,用法如下
url=reverse('名称空间的名字:待解析的别名')
2、在模版里基于名称空间的反向解析,用法如下
<a href="{% url '名称空间的名字:待解析的别名'%}">哈哈</a>
七django2.0バージョンre_pathとパス
7.1 re_path
URLのdjango1.0 re_path、のような、正規表現は、最初のパラメータである渡さDjango2.0
from django.urls import re_path # django2.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パス
などのデータ型変換と正規表現の冗長性、:解決するためにパス機能でDjango2.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采用了同样的正则表达式,重复编写了三遍,存在冗余问题,并且极不容易管理,因为一旦article_id规则需要改变,则必须同时修改三处代码
re_path(r'^article/(?P<article_id>[a-zA-Z0-9]+)/detail/$', views.detail_view),
re_path(r'^articles/(?P<article_id>[a-zA-Z0-9]+)/edit/$', views.edit_view),
re_path(r'^articles/(?P<article_id>[a-zA-Z0-9]+)/delete/$', views.delete_view),
]
views.py
from django.shortcuts import render,HttpResponse
# Create your views here.
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')
どのようにDjango2.0パスは、この2つの問題を解決するには?例を参照してください。
from django.urls import path,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/', views.detail_view),
path('articles/<int:article_id>/edit/', views.edit_view),
path('articles/<int:article_id>/delete/', views.delete_view),
]
彼は強調しました:
#1、path与re_path或者1.0中的url的不同之处是,传给path的第一个参数不再是正则表达式,而是一个完全匹配的路径,相同之处是第一个参数中的匹配字符均无需加前导斜杠
#2、使用尖括号(<>)从url中捕获值,相当于有名分组
#3、<>中可以包含一个转化器类型(converter type),比如使用 <int:name> 使用了转换器int。若果没有转化器,将匹配任何字符串,当然也包括了 / 字符
Djangoのデフォルトサポートどのような5種類のコンバータ(パスコンバータ)
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
例えば
path('articles/<int:year>/<int:month>/<slug:other>/', views.article_detail)
# 针对路径http://127.0.0.1:8000/articles/2009/123/hello/,path会匹配出参数year=2009,month=123,other='hello'传递给函数article_detail
我々は2つの文字を一致させたい場合は明らかに月の月の、int型のコンバータを正確に、一致しない場合、コンバータスラグは、需要を満たすことができず、非常に複雑なニーズのこのシリーズのために、我々は独自のコンバータを定義することができます。Converterは、クラスまたはインタフェースである、それは三点が必要です。
regex
クラス属性、文字列型to_python(self, value)
この方法は、値はクラス属性はregex
、文字列と一致している対応するDjangoのビュー関数への送達のために、可変のPythonの特定の値を返します。to_url(self, value)
方法、そしてto_python
逆に、値はストリング、一般的に使用される逆URL参照を返す特定の変数のPythonの値です。
カスタムコンバータの例:
- app01新しいファイルpath_のconverters.pyでは、ファイル名を命名することができます
class MonthConverter:
regex='\d{2}' # 属性名必须为regex
def to_python(self, value):
return int(value)
def to_url(self, value):
return value # 匹配的regex是两个数字,返回的结果也必须是两个数字
- urls.pyで使用した
register_converter
URLの設定に登録するには:
from django.urls import path,register_converter
from app01.path_converts import MonthConverter
register_converter(MonthConverter,'mon')
from app01 import views
urlpatterns = [
path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'),
]
- views.py article_detailビュー機能
from django.shortcuts import render,HttpResponse,reverse
def article_detail(request,year,month,other):
print(year,type(year))
print(month,type(month))
print(other,type(other))
print(reverse('xxx',args=(1988,12,'hello'))) # 反向解析结果/articles/1988/12/hello/
return HttpResponse('xxxx')
- テスト
# 1、在浏览器输入http://127.0.0.1:8000/articles/2009/12/hello/,path会成功匹配出参数year=2009,month=12,other='hello'传递给函数article_detail
# 2、在浏览器输入http://127.0.0.1:8000/articles/2009/123/hello/,path会匹配失败,因为我们自定义的转换器mon只匹配两位数字,而对应位置的123超过了2位