web-dev-qa-db-ja.com

Djangoオプションのurlパラメーター

次のようなDjango URLがあります。

url(
    r'^project_config/(?P<product>\w+)/(?P<project_id>\w+)/$',
    'tool.views.ProjectConfig',
    name='project_config'
),

views.py:

def ProjectConfig(request, product, project_id=None, template_name='project.html'):
    ...
    # do stuff

問題は、project_idパラメーターをオプションにすることです。

/project_config//project_config/12345abdce/を等しく有効なURLパターンにしたいので、ifproject_idが渡され、then使用できます。

現時点では、project_idパラメーターなしでURLにアクセスすると404が表示されます。

141
Darwin Tech

いくつかのアプローチがあります。

1つは、正規表現で非キャプチャグループを使用することです:(?:/(?P<title>[a-zA-Z]+)/)?
正規表現の作成Django URLトークンはオプション

もう1つの簡単な方法は、ニーズに一致する複数のルールを作成し、すべて同じビューを指すようにすることです。

urlpatterns = patterns('',
    url(r'^project_config/$', views.foo),
    url(r'^project_config/(?P<product>\w+)/$', views.foo),
    url(r'^project_config/(?P<product>\w+)/(?P<project_id>\w+)/$', views.foo),
)

ビューでは、オプションのURLパラメーターのデフォルトも設定する必要があることに注意してください。そうしないと、エラーが発生します。

def foo(request, optional_parameter=''):
    # Your code goes here
336

ネストされたルートを使用できます

ジャンゴ<1.8

urlpatterns = patterns(''
    url(r'^project_config/', include(patterns('',
        url(r'^$', ProjectConfigView.as_view(), name="project_config")
        url(r'^(?P<product>\w+)$', include(patterns('',
            url(r'^$', ProductView.as_view(), name="product"),
            url(r'^(?P<project_id>\w+)$', ProjectDetailView.as_view(), name="project_detail")
        ))),
    ))),
)

ジャンゴ> = 1.8

urlpatterns = [
    url(r'^project_config/', include([
        url(r'^$', ProjectConfigView.as_view(), name="project_config")
        url(r'^(?P<product>\w+)$', include([
            url(r'^$', ProductView.as_view(), name="product"),
            url(r'^(?P<project_id>\w+)$', ProjectDetailView.as_view(), name="project_detail")
        ])),
    ])),
]

これはさらに多くのDRY(product kwargの名前をproduct_idに変更したい場合、行4を変更するだけで、以下のURLに影響します。

Django 1.8以降用に編集済み

36
Jacob Valenta

さらに簡単です:

(?P<project_id>\w+|)

「(a | b)」はaまたはbを意味するため、あなたの場合は1つ以上のWord文字(\ w +)か、何もありません。

したがって、次のようになります。

url(
    r'^project_config/(?P<product>\w+)/(?P<project_id>\w+|)/$',
    'tool.views.ProjectConfig',
    name='project_config'
),
23

答えに少し追加すると思いました。

複数のURL定義がある場合は、それぞれに個別に名前を付ける必要があります。そのため、1つのリバースはパラメーターを期待し、もう1つのリバースはパラメーターを期待しないため、リバースを呼び出すときに柔軟性が失われます。

正規表現を使用してオプションのパラメーターに対応する別の方法:

r'^project_config/(?P<product>\w+)/((?P<project_id>\w+)/)?$'
9
tarequeh

Django> 2.0バージョン

このアプローチは、基本的に Yuji 'Tomita' Tomita's Answer に記載されているものと同じです。ただし、影響を受ける構文は次のとおりです。

# URLconf
...

urlpatterns = [
    path(
        'project_config/<product>/',
        views.get_product, 
        name='project_config'
    ),
    path(
        'project_config/<product>/<project_id>/',
        views.get_product,
        name='project_config'
    ),
]


# View (in views.py)
def get_product(request, product, project_id='None'):
    # Output the appropriate product
    ...

pathを使用すると、 ビューに追加の引数を渡す をオプションの引数としてdictとともに使用することもできます。この場合、ビューには属性project_idのデフォルトは必要ありません。

    ...
    path(
        'project_config/<product>/',
        views.get_product,
        name='project_config',
        {'project_id': None}
    ),
    ...

これがどのように行われるかについて最新のDjangoバージョンで、 公式URLディスパッチに関するドキュメント

5
jojo

ジャンゴ= 2.2

urlpatterns = [
    re_path(r'^project_config/(?:(?P<product>\w+)/(?:(?P<project_id>\w+)/)/)?$', tool.views.ProjectConfig, name='project_config')
]
1
AzizAhmad