質問

Djangoには、さまざまなフィルターパラメーターを受け入れることができるビューがありますが、それらはすべてオプションです。 6つのオプションのフィルターがある場合、6つの組み合わせのすべての組み合わせに対してURLを作成する必要がありますか、それともURLのどの部分がオプションであるかを定義する方法はありますか?

たった2つのフィルターで例を挙げると、これらのすべてのURLの可能性を持つことができます。

/<city>/<state>/
/<city>/<state>/radius/<miles>/
/<city>/<state>/company/<company-name>/
/<city>/<state>/radius/<miles>/company/<company-name>/
/<city>/<state>/company/<company-name>/radius/<miles>/

これらのURLはすべて同じビューを指しており、必要な唯一のパラマは都市と状態です。 6つのフィルターを使用すると、これは管理不能になります。

私が達成したいことをするための最良の方法は何ですか?

役に立ちましたか?

解決

1つの方法は、正規表現に指定されたすべてのフィルターを単一の文字列として読み取り、ビュー内の個々の値に分割することです。

次のURLを思いつきました。

(r'^(?P<city>[^/]+)/(?P<state>[^/]+)(?P<filters>(?:/[^/]+/[^/]+)*)/?$',
 'views.my_view'),

必要な都市と州に一致するのは簡単です。 filters 部分はもう少し複雑です。内側の部分 - (?:/[^/]+/[^/]+)* - フォームで与えられたフィルターを一致させます /name/value. 。しかし * 定量装置(すべてのPython正規表現の数量ファイヤーと同様)は、見つかった最後の一致のみを返します。したがって、URLがあった場合 /radius/80/company/mycompany/ それだけ company/mycompany 保管されます。代わりに、個々の値をキャプチャしないように言います( ?: 開始時)、すべてのフィルター値を単一の文字列として保存するキャプチャブロックの内側に置きます。

ビューロジックはかなり簡単です。正規表現はフィルターのペアのみに一致することに注意してください - したがって、 /company/mycompany/radius/ 一致しません。これは、値のペアがあると安全に想定できることを意味します。私がこれをテストしたビューは次のとおりです。

def my_view(request, city, state, filters):
    # Split into a list ['name', 'value', 'name', 'value']. Note we remove the
    # first character of the string as it will be a slash.
    split = filters[1:].split('/')

    # Map into a dictionary {'name': 'value', 'name': 'value'}.
    filters = dict(zip(split[::2], split[1::2]))

    # Get the values you want - the second parameter is the default if none was
    # given in the URL. Note all entries in the dictionary are strings at this
    # point, so you will have to convert to the appropriate types if desired.
    radius = filters.get('radius', None)
    company = filters.get('company', None)

    # Then use the values as desired in your view.
    context = {
        'city': city,
        'state': state,
        'radius': radius,
        'company': company,
    }
    return render_to_response('my_view.html', context)

これについて注意すべき2つのこと。まず、未知のフィルターエントリをビューに入れることができます。例えば、 /fakefilter/somevalue 有効です。上記のビューコードはこれらを無視しますが、おそらくユーザーにエラーを報告する必要があります。もしそうなら、値を取得するコードを変更します

radius = filters.pop('radius', None)
company = filters.pop('company', None)

に残っているエントリ filters 辞書は、文句を言うことができる不明な値です。

次に、ユーザーがフィルターを繰り返す場合、最後の値が使用されます。例えば、 /radius/80/radius/50 半径を50に設定します。これを検出する場合は、辞書に変換される前に値のリストをスキャンする必要があります。

given = set()
for name in split[::2]:
    if name in given:
        # Repeated entry, complain to user or something.
    else:
        given.add(name)

他のヒント

これは絶対にパラメーターを取得するためのユースケースです。あなたのurlconfはただなければなりません /city/state/, 、次に、変数を取得すると、さまざまなフィルターが最後に進みます。

/city/state/?radius=5&company=google

今、あなたの見解では、あなたは受け入れます citystate 通常のパラメーターとしてですが、他のすべては request.GET querydict。

また、1つのURL(パスの開始のみをチェックするだけで、同じであるはずです)を作成して、ビューを指してから解析することもできます。 request.path あなたの見解で。一方、さまざまな組み合わせに非常に多くのオプションのフィルターパラメーターがある場合、最良のソリューションは非常に頻繁にフィルタリングを行うことです。 GET- 特にフィルタリングに使用されるURLが検索エンジンに最適化する必要はない場合...

あなたのurls.pyでそのようなものを使用してみてください:

url(r'^(?P<city>[^/]+)/(?P<state>[^/]+)/(radius/(?P<miles>[^/]+)/|company/(?P<company_name>[^/]+)/)*$', 'view')
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top