2016-08-22 9 views
2

私のプロジェクトには、「abc」、「xyz」、「common」という3つのアプリケーションがあります。 Commonは、両方のアプリケーションによって継承され拡張されたテンプレート、モデル、ビューを格納するだけで、実際のアプリではありません。Djangoのアプリケーションが間違った名前空間に解決する

プロジェクトレベルのurls.pyはそうのように見え、かつ適切にそれぞれのアプリに要求をリダイレクトします。

urlpatterns = [ 
    url(r'^admin/', admin.site.urls), 
    url(r'^abc/', include('abc.urls')), 
    url(r'^xyz/', include('xyz.urls')), 
] 

は両アプリのurl.pyファイルには、次のようになり、唯一の違いは、XYZとABCのすべてのインスタンスを置き換えます:

再び
from django.conf.urls import url 
from views import ABCAlertList as AlertList 
from views import ABCEventList as EventList 
from views import ABCEventDetail as EventDetail 
from views import ABCEventReplay as EventReplay 
from views import ABCUploadView as UploadView 

urlpatterns = [ 
    url(r'^$', AlertList.as_view(), name='view_alerts'), 
    url(r'^entities/(?P<uid>\w+)/$', EventList.as_view(), name='view_uid'), 
    url(r'^entities/(?P<uid>\w+)/replay/$', EventReplay.as_view(), name='view_replay'), 
    url(r'^entities/(?P<uid>\w+)/event/(?P<eid>\w+)/$', EventDetail.as_view(), name='view_event'), 

    url(r'^upload/$', UploadView.as_view(), name='upload_file'), 
] 

何もアプリ固有のそれらのいずれかにがあるので、すべてのビューは、両方のアプリケーション間で共通しています。どちらのアプリは同じ共通のテンプレートに同じラインを使用します

<a href="{% url 'view_uid' alert.uid %}"> 

さて、問題:

のApp ABCは、トップレベルのページで正常に動作します。しかし、それが間違ったアプリを指していることを意味するURLをレンダリングしています。

例えば、私は

http://localhost:8888/abc/ 

になるだろうし、そのページのURLが与え何

http://localhost:8888/xyz/entities/262b3bce18e71c5459a41e1e6d52a946ab47e88f/ 

としてレンダリングしますか? Djangoが間違ったアプリのurls.pyを読んでいるようです。

+0

両方のurlsファイルに同じ名前がありますか?request.current_app属性を設定する必要があります。 ABCアプリでview_uidのようなものをabc_view_uidに変更してみてください。 XYZアプリではxyz_view_uidです。 – xrage

+0

/abc /ページのURLは、アプリケーションの他の部分へのリンクを意味しますか?もしそうなら、単なる単純なタイプミスのように聞こえるかもしれません。 ABCとXYZのurls.pyが適切な型であると仮定すると、Djangoが間違ったURLを作成する理由はわかりません。 –

答えて

6

Djangoは、ビュー名と引数だけでabc/xyz/のURLの違いを判別することはできません。逆転はパターンを逆順に実行するため、xyz/のパターンが常に最初に一致するため、reverse()タグまたは{% url %}タグを使用して生成されたすべてのリンクはxyzアプリを指します。

各パターンに一意の名前を付けるか、URL名前空間を使用する必要があります。ジャンゴでは、あなたがapp_name属性を設定する必要があり1.9+:Djangoの1.8では

app_name = 'abc' 
urlpatterns = [ 
    url(r'^$', AlertList.as_view(), name='view_alerts'), 
    url(r'^entities/(?P<uid>\w+)/$', EventList.as_view(), name='view_uid'), 
    url(r'^entities/(?P<uid>\w+)/replay/$', EventReplay.as_view(), name='view_replay'), 
    url(r'^entities/(?P<uid>\w+)/event/(?P<eid>\w+)/$', EventDetail.as_view(), name='view_event'), 

    url(r'^upload/$', UploadView.as_view(), name='upload_file'), 
] 

をあなたはinclude()namespaceパラメータを渡す必要があります:

urlpatterns = [ 
    url(r'^admin/', admin.site.urls), 
    url(r'^abc/', include('abc.urls', namespace='abc')), 
    url(r'^xyz/', include('xyz.urls', namespace='xyz')), 
] 

あなたはその後、適切な名前空間を渡すことによって、URLを逆にすることができます:

<a href="{% url 'abc:view_uid' alert.uid %}"> 

あなたが使用する必要がある場合両方のアプリケーションで同じテンプレートまたは関数を使用するには、両方のアプリケーションのアプリケーション名前空間を同じに設定する必要がありますが、別のインスタンス名前空間を使用する必要があります。 1.9+で

、これは同じapp_name属性を使用して意味するが、異なるnamespace引数渡し:テンプレートで

# myapp/urls.py 
app_name = 'common_app_name' 
urlpatterns = [ 
    # app urls 
] 

# myproject/urls.py 
urlpatterns = [ 
    url(r'^abc/', include('abc.urls', namespace='abc')), 
    url(r'^xyz/', include('xyz.urls', namespace='xyz')), 
] 

を、あなたは、URLを逆にするアプリケーションの名前空間を使用する必要があります。現在のインスタンス名前空間は自動的に考慮されます。reverse()への呼び出しでは、現在のネームスペースに合格する必要があります。

urlpatterns = [ 
    url(r'^abc/', include('abc.urls', namespace='abc', app_name='common_app_name')), 
    url(r'^xyz/', include('xyz.urls', namespace='xyz', app_name='common_app_name')), 
] 

ジャンゴ:Djangoの1.8では

reverse('common_app_name:view_alerts', current_app=request.resolver_match.namespace) 

あなたがapp_name属性を持っていない、あなたはinclude()にパラメータとして渡す必要があります1.8では、{% url %}タグの呼び出しで現在のインスタンス名前空間も自動的に使用されません。

def my_view(request): 
    request.current_app = request.resolver_match.namespace 
    ... 
+0

ありがとう、それは私が恐れていたものです。ドローイングボードに戻る:\ – Ivan

+0

...そうでないかもしれません。これらの制約を考えると、URLディスパッチャをバイパスして手動でコンパイルすると思います。 – Ivan

+1

@Ivanおそらく私の更新はあなたの特定のケースで役立つでしょうか?それ以外に、私はあなたの正確な問題が何であるか分からないので、私はそこにお手伝いできません。 – knbk

関連する問題