Django - page not found with VueJS [duplicate] - django

This question already has answers here:
Handling single page application url and django url
(7 answers)
Closed 1 year ago.
I'm trying to create a SPA with Vue in my Django project, so that Django handles only authentication templates and the rest of the frontend is entirely Vue rendered by webpack-loader, so it's Django rendering the Vue app. I'm doing this in order not to lose the benefits of having authentication handled entirely by Django.
So everything below /accounts/ will be handled by Django templates rendered by django views, while everything below /app/ will be handled by the Vue application.
I have the following:
urlpatterns = [
# Some standard django templates url here for authentication..
# ...
# The Vue app:
path('app/', views.vueApp, name='vueApp'),
]
So when the user navigates to mysite.com/app, Vue will handle the whole frontend as a SPA with its routes:
//main.js
const router = new VueRouter({
base: '/app',
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/test1', component: testcomponent },
{ path: '/test2', component: test2component }
]
})
The problem with my code, is that if i click on a link to test1 or to test2 from inside the Vue app, i will get redirected to testcomponent (mysite.com/app/test1) and test2component (mysite.com/app/test2); instead, if i open my browser and i navigate directly to mysite.com/app/test1 or mysite.com/app/test2 i will get a Page Not Found error by Django, i think because Django thinks i'm trying to reach a standard Django url, while instead i'm trying to reach an URL handled by my Vue app.
Is there any way to solve this? Thanks in advance!

To deal with this, you need a catch-all route to ensure that you capture everything after that / in your url as well. Otherwise it looks like your url is not a match. You need something like this (if you're using regex to match):
path('app/?.*$', views.vueApp, name='vueApp'),
This should match everything that starts with app/ and has other stuff after it as well. You don't care about capturing that stuff with django bc the vue router will handle it from that point.
ETA:
If you're NOT using regex, I think you can use this format to accept whatever comes after the slash:
path('app/<path:rest_of_path>', views.vueApp, name='vueApp'),

Related

Configuring React Routes, Django URLs using Webpack

Teaching myself how to use a React frontend with a Django server and I'm having difficulty getting the React routes to work properly. Whenever I reload the page it thinks I'm making a GET request to the server. Refreshing at localhost:8000 works fine, but anything other than an API route errors out.
Pretty sure the issue is in one of my urls.py files.
quiz_app/urls.py
urlpatterns = [
path('', include('quizzes.urls')),
path('', include('frontend.urls'))
]
frontend/urls.py
urlpatterns = [
path('', views.index )
]
quizzes/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path(r'^nested_admin/', include('nested_admin.urls')),
re_path('api/quizzes/', views.QuizList.as_view()),
re_path('api/quizzes/<str:name>/', views.SingleQuiz.as_view()),
re_path('api/questions/', views.QuestionList.as_view()),
re_path('api/answers/', views.AnswerList.as_view())
]
For good measure:
frontend/views.py
def index(request):
return render(request, 'frontend/index.html')
frontend/src/App.js
class App extends Component {
render() {
return (
<Router>
<div className="App">
<Grid>
<Header />
<Route exact path="/" component={Quizzes} />
<Route exact path="/:name" component={Quiz} />
</Grid>
</div>
</Router>
)
}
};
To reiterate, the issue is that the "/:name" routes in App.js are attempting to make "GET" requests to the Django server and erroring out because there's nothing to handle them rather than defaulting to a React route. Let me know what I'm doing wrong here. I've fixed this problem when using React with other server frameworks, but I'm new to Python/Django so not sure where to go from here.
If I understand your question correctly, then views.html renders the page that will run the app defined in App.js. And the problem you have is that if you go to a URL http://yourserver/my-quiz, where my-quiz is a quiz name, the request will be sent to the Django server, which says: 404, I don’t know about that URL.
One working solution is to add a catch-all route to your Django main app:
urlpatterns += re_path(r'.*', views.index)
as the last route. This simply makes Django render your app for each and every request, and react-router will take care of the routing.
The downside to this is that you won’t get a 404 if the page really doesn’t exist (in your case, there is no quiz by that name). I haven’t found a solution for that yet except duplicating routing configuration (in your case, checking in the Django app if a quiz with that name exists).
usually in the frontend framework like (angular, react, vue ) the routers only handle te calls in (the client side) and draw the correct component for each route so you need a component that works like a service, and there make calls to the backend api. e.j.
utility.js
export function get_some_route(){
return fetch('some_route');
}
the utility file contain functions to fetch the backend routes. so you can
import this file an get the data in the component rendered for the router.
your_component.js
import get_some_route from 'utility.js';
class x extends component{
...
componentDidMount(){
get_some_route().then(response => {
// do some thing with the data e.j
this.setState({data: response.data});
}
}
...
render(){
return(/*some html with the data */);
}
}
I had a simmilar issue but for me the django admin page was not showing. Adding this to my frontend/urls worked for me.
urlpatterns += re_path(r'^.*/$', views.index)

How do i configure django urls to make it so if it displays 404, it reroutes to Reactjs

The title is terrible - sorry about that.
So say I have a website say www.myhairynose.com/. I've configured my urls.py so that whenever the person enters www.myhairynose.com it redirects them to the index.html (where it displays the reactjs application). I've set reactjs with react-router and made it so when you click a button on the index page it goes to www.myhairynose.com/#/webpage.
Thing is... I don't want that.
I want it to go to www.myhairnose.com/webpage. I want react to handle this however and not django. ALL of this url thing should be in the same application of index.html. How do I configure django urls.py so that if I enter www.myhairynose.com/webpage it goes to the index of www.myhairnose.com ReactJs's application and then it checks to see if the route has webpage. Otherwise say if I went to www.myhairynose.com/asdkjaskldsaj (which the react route doesn't have) it should display a 404.
______TLDR______
Basically what I want to happen:
User goes to website.com/name
>if website.com/name exists in django - it returns a html doc
>if not then it redirects to website.com/ where ReactJs will handle the url and see if it matches any of the routers
...> if it does, then it displays that route
...> if not then it displays a django 404 or a custom 404 page.
How do I configure django and reactjs to do this?
Are you using Django to render react? I am making the assumption that you have some view like views.LoadReactView.
What you need is a catch all route.
from django.contrib import admin
from myapp import views
urlpatterns = [
...
url(r'^admin', admin.site.urls),
url(r'^', views.LoadReactView.as_view()),
]
This should appear as your very last pattern. You essentially are saying "after checking all the other routes, if there are no matches, go here".
In addition, you could also actually just define your main view as your 404 handler
urlpatterns = [
...
]
handler404 = views.LoadReactView.as_view

Redirecting old PHP links to Django urls

I am getting a lot of search engine referral links for my previous PHP developed site that has now been migrated over to Django. I made a url redirect for the old php links like search.php?name=john+smith to the same view for my django search url as shown here:
urls.py
url(r'^search.php/$', profile_search, name='search'),
url(r'^search/$', profile_search, name='search'),
Will Google eventually update those old links if I redirect through urls.py or do I need to make a 301 redirect? If so how would I do this with django and nginx?
I would do this at nginx level - this is much more efficient than having Django handle it. Assuming the Django view expects the same query arguments, you can do this in your nginx server block:
location = /search.php {
return 301 http://$server_name/search/$is_args$args;
}
This will redirect all requests for search.php to /search/, preserving any query arguments.
A 301 response is definitely the correct approach - you don't want to serve duplicate content on different URLs.
Unless you have HttpResponseRedirect in your profile_search method, you don't actually have any sort of redirect here at. But what you really want to use is HttpResponsePermanentRedirect
def profile_search(request):
return HttpResponsePermanentRedirect('/somether/url/?based_on_request_params')

Angular-ui-router not rendering templates with django

I am working on a django project that relies on angularjs and having trouble implementing angular-ui-router framework.
As mentioned in documentation I have included ui.router as a dependency,
app = angular.module('myApp',['restangular','ui.router',])
configured the states as follows,
app.config(['$stateProvider',function($stateProvider){
$stateProvider.state('landing',{
url: '/',
template:"<p> somethings here.</p>"
})
}]);
in base.html file i bootstrap the django project with angularjs as required
ng-app=myApp.
and in index.html which inherits base.html
<div ui-view>
<i>nothing here but this text</i>
</div>
my urls.py,
url(r'^$',home,name="homepage")
This does not work, ui-router never includes the inline template in index.html. index.html always loads nothing here but this text. I have looked at as much questions asked here but are not helping. What am I missing, is this specific to django?
I would say that these lines should make it:
app.config(['$urlRouterProvider',function($urlRouterProvider){
$urlRouterProvider.otherwise('/');
}]);
Check the working plunker here
Also check:
otherwise() for invalid routes

Django and backbone templates

I have a working backbone application. The backend is Django.
I have a Detail View of posts that uses an underscore.js template with a bit of logic:
For example:
{[ _.each(model.images, function(i){ ]} <img src="{{i.image}}"> {[ }); ]}
I now want to create the server-side view, in order to serve the url example.com/details/10
What would be the best way of reusing the underscore.js template? Or should I just copy/paste it into another file and change it to the django templating language?
Have a look here to get an idea of how you could efficiently structure such an application.
The django app is inside the blog directory(look at the static/app.js)