これはいくつかの方法で実現できました(4番目はサブドメインを使ったボーナスです)。すべてが地域を検出し、要求にそれを設定するミドルウェアを想定しています。
@ RemcoGerlichのヒントの後、DjangoがURLの国際化をどのように処理するかを模倣します。 LocaleMiddleware
は言語を検出し、その要求にアクティブな言語を設定します(スレッドローカル変数を使用)。次に、そのアクティブな言語を使用してi18n_patterns()を作成します。実際にはURLの代わりにLocaleRegexURLResolver
(通常のリゾルバのサブクラスを返します)を返します。他のタイプのプレフィックスをサポートするために同様のことができると私は信じています。
さらに強気なアプローチは、Djangoがアクティブな言語のために行うように、リクエスト内だけでなくスレッドローカル変数にも領域を再度格納することです。 URLを更新して、リージョンプレフィックスの名前付き引数を持ち、ビュー引数に追加します。カスタムリバースを実装して、リージョンパラメータを追加します。悪を行う傾向がある場合は、これをモーフキーで囲んで、reverse
とurl
のテンプレートリファレンスをすべて触れることを避けることができます。
領域に基づいてset the request.urlconf
にミドルウェアを使用して、ROOT_URLCONF
を上書きします。これは、この要求に対してのみ異なる一連のURLを提供します。リージョンごとに1つの新しいURLconfを作成し、接頭辞を追加してベースURLconfを追加します。ビューのパラメータでパスの領域部分を取り込む必要はありません。 URLを逆転することは "うまくいく"ことです。
私がしなかったサブドメインを使用したい場合は、この質問に参照されているdjango-hosts
というDjango Appがあります:Django: Overwrite ROOT_URLCONF with request.urlconf in middleware。
私のアプリケーションでは、request.urlconf
をミドルウェアでオーバーライドするのが最も簡単で洗練されたソリューションでした。ここではミドルウェアからの断片です:
# ... detect region first based on path, then session, and and maybe later IP address...
# Then force the URLconf:
if request.region == Region.EU:
request.urlconf = "mysite.regional_urls.eu_urls"
else:
request.urlconf = "mysite.regional_urls.us_urls"
私は地域ごとに新しいのURLconfを作成したが、彼らはDRYワンライナーです:
urlpatterns = create_patterns_for_region(Region.EU)
これらは私がなりたかったURLの両方を組み合わせたテンプレートを参照
from django.conf.urls import patterns, include, url
def create_patterns_for_region(region):
return patterns(
'',
# First match regional.
url(r'^{}/'.format(region.short), include('mysite.regional_urls.regional_base_urls')),
# Non-regional pages.
url(r'', include('mysite.regional_urls.nonregional_base_urls')),
# Any regional URL is missing.
url(r'^{}/.*'.format(Region.REGION_PREFIX), error_views.Custom404.as_error_view()),
# Attempt to map any non-regional URL to region for backward compatibility.
url(r'.*', RegionRedirect.as_view()),
)
そして最後に、下位互換性のためにリダイレクトビュー:
私は「裸」のままにしたかったものと地域
class RegionRedirect(RedirectView):
""" Map paths without region to regional versions for backward compatibility.
"""
permanent = True
query_string = True
def get_redirect_url(self, *args, **kwargs):
self.url = "/" + self.request.region.short + self.request.path
return super(RegionRedirect, self).get_redirect_url(*args, **kwargs)
領域をインクルードするようにキャッシュを更新してください。 ;)
ありがとうございました。私は主にSEOのために悪いと知られているので、サブドメインを排除しました。たとえば、私は既存のサイトのドメインクレジットを新しい地域で私に恩恵を与えたいと思っています。私は言語のドキュメントを見なければならないでしょう。 –
はい、彼らが言語のためにやっていることはまさに私がやろうとしていることです。私は、https://docs.djangoproject.com/en/1.10/topics/http/urls/#including-other-urlconfsをincludeを使用してurlconf側で同じことをすることができますが、逆転作業の仕方はわかりません。 –
そして、インクルードでさえ、パスから言語コードを取り除き、それをビューの引数として送信しないという自動化の動作を提供しません。私も欲しいものです。 –