I have a single page application created in Vue.js that utilizes the HTML5 History Mode for routing, and the html file is served with Django.
The urls.py of django is like so:
urlpatterns = [
url(r'^$', views.home),
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
]
And views.home:
def home(request):
return render(request, 'index.html')
Consider the following scenario:
- User visits the home page (i.e.,
/
)
Since, the home page responds with required index.html for the Single page Vuejs app, it works like its supposed to.
- From there the user navigates to the about page (i.e.,
/username/12
).
Its still working fine, as its navigating with the Vue router.
- Now, the user refreshes the page.
Since there's no /username/12
in the urls.py patterns, it will show Page not found (404).
Now, I could provide another pattern in urls.py to catch all pattern in the last order as this:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-token-auth/', obtain_jwt_token),
url(r'^.*$', views.home),
]
But other urls like the media or static urls will also point to the same catch all pattern regex. How can I solve this problem?
I solved the issue by using the negative look-ahead regex, so basically anything inside
(?!ignore1|ignore2)
will be ignored.Note: I tried not including
admin
andapi-token-auth
inside the negative look-ahead and it didn't work for me, it will still route path that starts withadmin
to theviews.home
, not sure why as according to my understanding, django should match the earlier ones first.Since you have mentioned "single page":
The server is supposed to serve just one page the
index.html
(or whatever else you would like to call it).The server and the web application (front-end) code would communicate via api calls, such that the server provides resources and the web-app takes care of using that resource.
In case of a missing resource, the server still must not respond with a separate page, it should still respond with a message that the web-app can use.
I believe you are using vue-router, which simulates the single-page app to be a full-featured, multi-page application.
You may want to take a look at this and this, but the above holds true for a single page application.
You shared your urlpatterns:
A way you can manage that would be either by, serving on a route other than
'/'
like mentioned above for/app
.and in your router.js file:
Or prefixing the purpose served by the urls like
Since index.html is templated (a dynamic page) because it's served from your views instead of static, this becomes a bit weird.
For production, definitely use nginx or apache to serve the static content in a similar fashion.
For development, this is what I would do:
This is my solution to this problem. Hope it helps you.
Expected results:
and I try this and it works!
urls.py
and this is my vue router
My project on GitHub
I'm using VueJS router enabled history mode with Django 2.x by this way:
From app urls.py you need to
repath
your frontend url like this:Now history mode working smoothly!
Become:
The answer provided above by @billi works fine, up to a point. My problem is that for my SPA I want (need?) to use the Vue <router-view> and <router-link> system. But the router.js maps paths to Vue components, and some of my paths are to Django views via Django urls.py - for example, this will result in a blank page if navigating to /api/places from the Vue router nav, but will resolve correctly to a Django if refreshed.
Ideas?
urls.py
router.js
App.vue