Configuring React Routes, Django URLs using Webpack - django

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)

Related

Django - page not found with VueJS [duplicate]

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'),

Create a 'dummy' URL path for frontend pictures rendering

I have application with DjangoRestFramework for backend and Vue.js for frontend.
My user can upload pictures and they are stored in an uploaded_media file.
Therefore I added + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) to my urlpatterns.
But since it is a Single Page Application, I added re_path(r"^.*$", IndexTemplateView.as_view(), name="entry-point"), in my urlpatterns for everything to be redirected to my index.html.
My issue is since my pictures URL is fetched in this format: "http://127.0.0.1:8000/media/my_pic.jpg", it can't be rendered frontend because it's redirected to my entry-point.
So I made a 'dummy' URL path (path('media/', DummyView.as_view())) pointing to a dummy View:
class DummyView(TemplateView):
pass
And it works... just for the first picture. I am doing it right and missing something or I am going to the wrong direction?
If it helps, I find a better way than creating a 'dummy' view, I just change my entry-point URL this way:
re_path(r"^(?!media).*$", IndexTemplateView.as_view(), name="entry-point")
So everything except the URL starting with 'media' is redirected to the entry-point

Im using Django as Backend and Reactjs as Frontend, So what must i use to route the urls

What must i use for routing urls?
Using React-Router or Urls from Django?
ReactJS Route:
<Router>
<Route path="/" exact component={StatefullComponent} />
<Route path="/blog" exact component={BlogPost} />
<Route path="/blog/detail/:id" component={DetailPost} />
</Router>
Django Route(Urls):
urlpatterns = [
url(r'^blog/', include('blog.urls', namespace='blog')),
]
Question:
1.Which route is better?
2.Can i use both route for my urls?
3.If i use django urls, my frontend will using single page route like react did?
I personally prefer ReactJS handle the routing, where using django to serve the react. So I prefer using the following pattern in django:
urlpatterns = [
url(r'^.*$', TemplateView.as_view(template_name='react_template_name.html')),
]
In this pattern, url accepts any path and servers ReactJs app in that. Then React Router takes over and does the rest of the routing.

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

Django URL template match (everything except pattern)

I need a django regex that will actually work for the url router to do the following:
Match everything that does not contain "/api" in the route.
The following does not work because django can't reverse (?!
r'^(?!api)
The usual way to go about this would be to order the route declarations so that the catch-all route is shadowed by the /api route, i.e.:
urlpatterns = patterns('',
url(r'^api/', include('api.urls')),
url(r'^other/', 'views.other', name='other'),
url(r'^.*$', 'views.catchall', name='catch-all'),
)
Alternatively, if for some reason you really need to skip some routes but cannot do it with the set of regexes supported by Django, you could define a custom pattern matcher class:
from django.core.urlresolvers import RegexURLPattern
class NoAPIPattern(RegexURLPattern):
def resolve(self, path):
if not path.startswith('api'):
return super(NoAPIPattern, self).resolve(path)
urlpatterns = patterns('',
url(r'^other/', 'views.other', name='other'),
NoAPIPattern(r'^.*$', 'views.catchall', name='catch-all'),
)
Use a negative look behind like so:
r'^(?!/api).*$'
This link explains how to do that:
http://www.codinghorror.com/blog/2005/10/excluding-matches-with-regular-expressions.html
I had this problem integrating django with react router, I check this link to fix it.
decoupled frontend and backend with Django, webpack, reactjs, react-router