web-dev-qa-db-ja.com

単一ページのアプリケーションURLとDjango urlの処理

ルーティングにHTML5履歴モードを利用するVue.jsで作成された単一ページアプリケーションがあり、htmlファイルはDjangoで提供されます。

rls.py Djangoは次のようになります:

urlpatterns = [
    url(r'^$', views.home),
    url(r'^admin/', admin.site.urls),
    url(r'^api-token-auth/', obtain_jwt_token),
]

そしてviews.home

def home(request):
    return render(request, 'index.html')

次のシナリオを検討してください。

  1. ユーザーがホームページにアクセスした(例:/

ホームページは単一ページのVuejsアプリに必要なindex.htmlで応答するため、想定どおりに動作します。

  1. そこから、ユーザーは概要ページ(つまり、/username/12)に移動します。

Vue router。

  1. これで、ユーザーはページを更新します。

rls.pyパターンには/username/12がないため、Page not found(404)と表示されます。

今、私はrls.pyに別のパターンを提供して、次のように最後の順序ですべてのパターンをキャッチできます:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api-token-auth/', obtain_jwt_token),
    url(r'^.*$', views.home),
]

ただし、メディアや静的URLなどの他のURLも同じcatch all pattern regexを指します。この問題を解決するにはどうすればよいですか?

19
Robin

同様の問題があります。

どのようにしてvue-routerとDjango RESTフレームワークを同時に使用できますか?

これがこの問題に対する私の解決策です。お役に立てば幸いです。

予期された結果:

_http://127.0.0.1:8000/       <-- TeamplateView index.html using vue
http://127.0.0.1:8000/course <-- vue-router
http://127.0.0.1:8000/api    <-- rest framework
http://127.0.0.1:8000/admin  <-- Django admin
_

これを試してみるとうまくいきます!

urls.py

_urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^api/', include(router.urls)),
    url(r'^.*$', TemplateView.as_view(template_name="index.html")),
]
_

順序は重要です。url(r'^.*$', TemplateView.as_view(template_name="index.html")),が最後です

これは私のvue router

_const router = new VueRouter({
  mode: 'history',
  base: __dirname,
  routes: [{
      path: '/courses',
      component: CourseSet
    }, {
      path: '/',
      component: hello
    }]
})
_

GitHub上の私のプロジェクト

17
Bllli

「単一ページ」について言及したので、

  1. サーバーは、index.html(またはそれ以外の任意のページ)を1ページだけ提供することになっています。

  2. サーバーとWebアプリケーション(フロントエンド)コードは、API呼び出しを介して通信し、サーバーがリソースを提供し、Webアプリがそのリソースを使用するようにします。

  3. リソースが欠落している場合でも、サーバーは別のページで応答してはならず、Webアプリが使用できるメッセージで応答する必要があります。

ルーティングにHTML5履歴モードを利用するVue.jsで作成された単一ページアプリケーションがあります。

vue-router を使用していると思います。これは、シングルページアプリをフル機能のマルチページアプリケーションとしてシミュレートします。


thisthis を確認することをお勧めしますが、上記は単一ページのアプリケーションにも当てはまります。


Urlpatternsを共有しました:

urlpatterns = [
  url(r'^admin/', admin.site.urls),
  url(r'^api-token-auth/', obtain_jwt_token),
  url(r'^.*$', views.home),
]

ただし、メディアや静的URLなどの他のURLも、同じキャッチオールパターン正規表現を指します。この問題を解決するにはどうすればよいですか?

  1. これを管理する方法は、'/'について上記で説明したように、/app以外のルートでサービスを提供することです。

    urlpatterns = [
      url(r'^admin/', admin.site.urls),
      url(r'^api-token-auth/', obtain_jwt_token),
      url(r'^.*$/app', views.home),
    ]
    

    そしてあなたのrouter.jsファイルで:

    new Router({
      mode: 'History',
      base: '/app'
      routes: [
        {
          path: '/',
          name: 'name',
          component: ComponentName
        }
      ]
    })
    
  2. または、次のようなURLが提供する目的の前に

    urlpatterns = [
      url(r'^api/admin/', admin.site.urls),
      url(r'^api/api-token-auth/', obtain_jwt_token),
      url(r'^.*$', views.home),
      url(r'^.*$/assets', your-static-assets) 
    ]
    
4

Index.htmlは静的ではなくビューから提供されるため、テンプレート(動的ページ)であるため、これは少し奇妙なものになります。

本番環境では、必ずnginxまたはApacheを使用して、同様の方法で静的コンテンツを提供してください。

開発のために、これは私がすることです:

from Django.contrib.staticfiles.views import serve

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api-token-auth/', obtain_jwt_token),
]

# Serve your static media (regex matches *.*)
if settings.DEBUG:
    urlpatterns.append(url(r'(?P<path>.*\..*)$', serve))

# Serve your single page app in every other case
urlpatterns.append(url(r'^.*$', views.home))
0
Kenneth

私は否定的な先読み正規表現を使用して問題を解決したので、基本的に(?!ignore1|ignore2)内のすべては無視されます。

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api-token-auth/', obtain_jwt_token),
    url(r'^(?!admin|api-token-auth|static).*$', views.home),
]

注:否定的な先読み内にadminapi-token-authを含めないようにしましたが、うまくいきませんでした。adminで始まるパスをviews.homeにルーティングしますが、理由はわかりません私の理解によると、Djangoは最初のものと最初に一致するはずです。

0
harinsa

上記の@billiによる回答は、ある程度まではうまく機能します。私の問題は、SPAにVue <router-view>と<router-link>システム。しかし、router.jsはパスをVueコンポーネントにマッピングし、私のパスの一部はDjango urls.pyを介してDjangoビューに移動します。たとえば、これにより、ナビゲーションVueルーターナビゲーションから/ api/placesに変更しますが、更新するとDjangoに正しく解決されます。

アイデア?

rls.py

urlpatterns = [
    # Django
    path('admin', admin.site.urls),
    url(r'^api-auth/', include('rest_framework.urls')),
    url(r'^api/places$', views.PlaceList.as_view()),

    # catchall to Vue single page app
    url(r'^.*$', TemplateView.as_view(template_name='myapp/spa.html'), name='home'),
]

router.js

export default new Router({
  mode: 'history',
  routes: [
    {path: '/search', component: Search},
    {path: '/about', component: About},
    {path: '/', component: Home},
    {path: '/api/places', }
  ]
})

App.vue

<template>
  <div id="app">
    <div>
    <router-link to="/search">Search</router-link> ::
    <router-link to="/about">About</router-link>
    <router-link to="/">Home</router-link> ::
    <router-link to="/api/places">Place API</router-link> ::
  </div>
  <router-view></router-view>
  </div>
</template>
0
kgeo