J'ai une application d'une seule page créée dans Vue.js qui utilise le mode Historique HTML5 pour le routage, et le fichier html est servi avec Django.
rls.py de Django est comme ceci:
urlpatterns = [
url(r'^$', views.home),
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
]
Et views.home:
def home(request):
return render(request, 'index.html')
Considérez le scénario suivant:
/
)Depuis, la page d'accueil répond avec index.html requis pour l'application Vuejs à page unique, elle fonctionne comme elle est censée le faire.
/username/12
).Son fonctionne toujours bien, comme sa navigation avec le routeur Vue.
Puisqu'il n'y a pas de /username/12
dans les modèles rls.py, il affichera Page non trouvée (404).
Maintenant, je pourrais fournir un autre modèle dans rls.py pour attraper tous les modèles dans le dernier ordre comme ceci:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^.*$', views.home),
]
Mais d'autres URL comme les médias ou les URL statiques pointeront également vers la même capture toutes les expressions régulières de modèle . Comment puis-je résoudre ce problème?
J'ai le même problème.
Comment utiliser en même temps vue-router et Django rest framework ?
Ceci est ma solution à ce problème. J'espère que cela vous aide.
Résultats attendus:
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
et j'essaye ça et ça marche!
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")),
]
L'ordre est important,
url(r'^.*$', TemplateView.as_view(template_name="index.html")),
est le dernier
et c'est mon vue routeur
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [{
path: '/courses',
component: CourseSet
}, {
path: '/',
component: hello
}]
})
Puisque vous avez mentionné "une seule page":
Le serveur est censé servir une seule page le index.html
(ou comme vous voudriez l'appeler autrement).
Le serveur et le code de l'application Web (frontal) communiqueraient via des appels API, de sorte que le serveur fournit des ressources et que l'application Web se charge d'utiliser cette ressource.
En cas de ressource manquante, le serveur ne doit toujours pas répondre avec une page séparée, il doit quand même répondre avec un message que l'application web peut utiliser.
J'ai une application d'une seule page créée dans Vue.js qui utilise le mode Historique HTML5 pour le routage
Je pense que vous utilisez vue-router , qui simule l'application d'une seule page pour être une application multi-page complète.
Vous voudrez peut-être jeter un œil à this et this , mais ce qui précède est vrai pour une application d'une seule page.
Vous avez partagé vos motifs d'URL:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^.*$', views.home),
]
Mais d'autres URL comme les médias ou les URL statiques pointeront également vers le même catch regex de motif. Comment puis-je résoudre ce problème?
Vous pouvez gérer cela en utilisant une route autre que '/'
comme mentionné ci-dessus pour /app
.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^.*$/app', views.home),
]
et dans votre fichier router.js:
new Router({
mode: 'History',
base: '/app'
routes: [
{
path: '/',
name: 'name',
component: ComponentName
}
]
})
Ou préfixer le but servi par les URL comme
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)
]
Étant donné que index.html est basé sur un modèle (une page dynamique) car il est servi à partir de vos vues au lieu de statique, cela devient un peu bizarre.
Pour la production, utilisez certainement nginx ou Apache pour servir le contenu statique d'une manière similaire.
Pour le développement, voici ce que je ferais:
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))
J'ai résolu le problème en utilisant l'expression rationnelle négative, donc essentiellement tout ce qui se trouve à l'intérieur (?!ignore1|ignore2)
sera ignoré.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^(?!admin|api-token-auth|static).*$', views.home),
]
Remarque: J'ai essayé de ne pas inclure admin
et api-token-auth
à l'intérieur de l'anticipation négative et cela n'a pas fonctionné pour moi, il acheminera toujours le chemin commençant par admin
vers views.home
, je ne sais pas pourquoi, selon ma compréhension, Django devrait d'abord correspondre aux précédents.
La réponse fournie ci-dessus par @billi fonctionne très bien, jusqu'à un certain point. Mon problème est que pour mon SPA, je veux (besoin?) D'utiliser la vue de routeur Vue <> et < router-link > system. Mais le router.js mappe les chemins vers les composants Vue, et certains de mes chemins sont à Django vues via Django urls.py - par exemple, cela se traduira par une page vierge si vous accédez à/api/places à partir du Vue nav du routeur, mais se résoudra correctement en un Django si actualisé.
Des idées?
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>