2016-12-24 6 views
0

私は、eコマースサイトを地域(米国、EUなど)に変換するので、基本的にコンテンツに基づいて訪問者とは異なるサイトのように感じます彼らは実際には1つのサイト(多くの理由で)でも、彼らは見るでしょう。私のサイト上のほとんどのパスは、パスの先頭に '/ us /'のように接頭辞を付けることで、地域固有のものになります(しかし、すべてを変換することができます。Djangoでは、ほとんどのパスに地域プレフィックスを追加する方法

マイプラン:

  • ミドルウェアは、1)リクエスト経路、2)セッション、または3)の順でIPアドレスに基づいて推測に基づく領域を識別し、それがリクエストオブジェクトに設定されています。また、地域パスを使用すると、セッション値として格納されます。このようにして、領域コンテキストは、領域特有ではないURLにわたって搬送される。

  • 地域固有のURLパターンは、ロジックが単なるパスよりも複雑だったため、ミドルウェアですでに領域を検出していても、地域に合わせて更新する必要があります。それにもかかわらず、私はそれをパラメータにして、次の理由(逆転)のために、私の意見をすべて伝えなければなりません。また、地域になっている経路は、その以前のパターン301をその地域経路にリダイレクトする。

  • リージョン固有のリンクを生成するには、region引数を追加してreverse()および{%url%}への呼び出しを多く更新する必要があります。リクエストの知識を持ってURLを動的に逆転させるようにカスタマイズできるレイヤーがここにあることを願っています。

私の主な質問は、反転(最後の箇条書き)を処理する最良の方法です。それは多くの不必要な仕事のように感じる。私は問題を全体的に解決するためのより良い方法について開いています。

更新:

  • 彼らは権威を転送する、SEOのために悪いことが知られているので、私はサブドメインを除外。また、サブドメインはまったく異なる設定を意味すると考えられますが、今はこれを1つのWebアプリケーションとして管理します。
  • @RemcoGerlichが指摘するように、基本的に、LocaleMiddleware/i18n_patternsがurlconfと反転の両方で追加するオートマジックの振る舞いを追加したいと思います。

答えて

2

これはいくつかの方法で実現できました(4番目はサブドメインを使ったボーナスです)。すべてが地域を検出し、要求にそれを設定するミドルウェアを想定しています。

  1. @ RemcoGerlichのヒントの後、DjangoがURLの国際化をどのように処理するかを模倣します。 LocaleMiddlewareは言語を検出し、その要求にアクティブな言語を設定します(スレッドローカル変数を使用)。次に、そのアクティブな言語を使用してi18n_patterns()を作成します。実際にはURLの代わりにLocaleRegexURLResolver(通常のリゾルバのサブクラスを返します)を返します。他のタイプのプレフィックスをサポートするために同様のことができると私は信じています。

  2. さらに強気なアプローチは、Djangoがアクティブな言語のために行うように、リクエスト内だけでなくスレッドローカル変数にも領域を再度格納することです。 URLを更新して、リージョンプレフィックスの名前付き引数を持ち、ビュー引数に追加します。カスタムリバースを実装して、リージョンパラメータを追加します。悪を行う傾向がある場合は、これをモーフキーで囲んで、reverseurlのテンプレートリファレンスをすべて触れることを避けることができます。

  3. 領域に基づいてset the request.urlconfにミドルウェアを使用して、ROOT_URLCONFを上書きします。これは、この要求に対してのみ異なる一連のURLを提供します。リージョンごとに1つの新しいURLconfを作成し、接頭辞を追加してベースURLconfを追加します。ビューのパラメータでパスの領域部分を取り込む必要はありません。 URLを逆転することは "うまくいく"ことです。

  4. 私がしなかったサブドメインを使用したい場合は、この質問に参照されている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) 

領域をインクルードするようにキャッシュを更新してください。 ;)

1

ない本当の答え、ちょうど2つの提案:

  1. は、あなたがサブドメインを使用することができませんか?ミドルウェアと同じアイデアですが、URL生成から独立しています。

  2. Djangoはあなたのアイデアをサポートしていますが、リージョン(docs here)ではなく言語に対応しているかもしれませんが、おそらくあなたはそれを適応させることができます。

+0

ありがとうございました。私は主にSEOのために悪いと知られているので、サブドメインを排除しました。たとえば、私は既存のサイトのドメインクレジットを新しい地域で私に恩恵を与えたいと思っています。私は言語のドキュメントを見なければならないでしょう。 –

+0

はい、彼らが言語のためにやっていることはまさに私がやろうとしていることです。私は、https://docs.djangoproject.com/en/1.10/topics/http/urls/#including-other-urlconfsをincludeを使用してurlconf側で同じことをすることができますが、逆転作業の仕方はわかりません。 –

+0

そして、インクルードでさえ、パスから言語コードを取り除き、それをビューの引数として送信しないという自動化の動作を提供しません。私も欲しいものです。 –

関連する問題