使用 Django + react-router 找不到 404 页面

Posted

技术标签:

【中文标题】使用 Django + react-router 找不到 404 页面【英文标题】:404 page not found using Django + react-router 【发布时间】:2016-01-18 05:12:00 【问题描述】:

我正在尝试在我的 Django 应用程序中使用 reactjsreact-router (1.x),但我很难将所有这些放在一起。这是 github 项目,以防我在这个问题中没有提供足够的信息。

https://github.com/liondancer/django-cherngloong

我在我的routes.js 中创建了一个path="about"

var routes = (
    <Router>
        <Route path="/" component= Views.Layout >
            <IndexRoute component= Views.Index  />
            <Route path="about" component= Views.About  />
        </Route>
        <Route path="*" component= Views.RouteNotFound  />
    </Router>
);

export default routes;

我的layout.js

class Layout extends React.Component 
    constructor(props) 
        super(props);
    
    render() 
        return (
            <div id="review-web">
                <header className="header">
                    <LogoElement />
                    <CenterPiece />
                </header>
                <div>
                     React.cloneElement(this.props.children,  path: this.props.path ) 
                </div>
                <Footer />
            </div>
        );
    


export default Layout;

当我输入localhost.8000/about 时,我收到404 Django 错误

我的目标是保持前端和后端分开,所以我相信我应该能够将 Django 用作数据的端点,而不是呈现视图。

【问题讨论】:

当您转到“/”时,它是否成功地服务于 Views.Layout 页面?在我看来,您的应用程序似乎不知道服务器或查看 routes.js。您是否将应用配置为使用 routes.js? @user2719875 现在我的应用程序使用this 来使用route.js。如果我输入localhost:8000/,它将显示this组件] 如果你这样做,它会起作用吗: (请参阅我在路径开头使用的斜杠)。编辑:另外,你确定你不想单独包含这一行“”吗?它目前嵌套在另一条路线内。 您需要在 Django 应用程序中拆分您的路线处理 - 例如直接为 Django 提供以/api/* 为前缀的任何内容,以及为/path/to/your/index.html 提供任何其他(通配符) - 这是您的 React 应用程序。否则 Django 将 /about 路由解释为它自己的 - 它不会与 React 应用程序对话(它不能)。 @elithrar 好主意!但如果是通配符 * 服务器将为每个请求返回 http status_code 200,但是对于不存在的 url 返回 http status_code 404 很好。 【参考方案1】:

我的应用为所有有效路由提供相同的客户端 JS。请原谅 Flask 代码。

@blueprint.route('/stuff/<path:path>', methods=["get"])
@blueprint.route('/', methods=["get"])
def index(path=None):
    return render_template('app.html')

【讨论】:

【参考方案2】:

我遇到了同样的问题,最终得到了这个解决方案。

settings.py:

REACT_ROUTES = [
    'login',
    'signup',
    'password-reset',
    'password-change',
    'about',
    ...
]

urls.py:

routes = getattr(settings, 'REACT_ROUTES', [])
urlpatterns = [
    ...
    url(r'^(%s)?$' % '|'.join(routes), TemplateView.as_view(template_name='index.html')),
]

我不喜欢在 django 设置中复制所有 react-routes,但是如果我们将所有内容都放在那里 url(r'^.*$'),服务器将始终返回 HTTP status_code 200。这只是能够返回有效 HTTP status_code 404 的一种方法对于不存在的网址。

【讨论】:

有人可以将“url”行翻译成 Django 2(+)“路径”吗?我的理解目前太有限,无法做到。虽然我现在会看它,并在我解决它时更新答案。 嗨,感谢您的帖子,我只想问一下,react-router 端是否可以处理 404 错误?据我了解,django 仍然拥有无与伦比的路线.. 在 Django 2+ 中,现在不推荐使用 url,您可以使用 re_path【参考方案3】:

根据 ramusus 的回答,这就是我现在修复它的方式。

由于 url 不再适用于 Django 2 及更高版本。 ramuses 的答案似乎也在使用 Python 2,查看字符串格式。这是使用 Python 3(.6)。

(虽然我确信有一种更优雅的方法可以做到这一点,但它确实有效,并帮助我在启动和运行项目方面更进一步。)

settings.py:(正如 ramusus 建议的那样)

REACT_ROUTES = [
    'login',
    'signup',
    'password-reset',
    'password-change',
    'about',
    ...
]

在主 urls.py 中:(部分按照 ramusus 的建议)

from django.conf import settings

react_routes = getattr(settings, 'REACT_ROUTES', [])

for route in react_routes:
    urlpatterns += [
        path(''.format(route), TemplateView.as_view(template_name='index.html'))
    ]

【讨论】:

您可以在 Django 2 中使用 django.urls.re_path 来替代 django.conf.urls.url: docs.djangoproject.com/en/2.1/ref/urls/#re-path【参考方案4】:

我的灵感来自ramusus' answer。我正在使用(我认为)较新的django.urls.re_path。我对this comment 有点怀疑,如果 404 由前端处理会更好或更糟。这就是我实现它的方式:

前端/views.py

from django.shortcuts import render

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

前端/urls.py

from django.urls import re_path

# Catch all pattern
urlpatterns = [
    re_path('.*/', views.index, name='index'),
]

main/urls.py

from django.contrib import admin
from django.urls import path, include
from rest_framework.authtoken import views


urlpatterns = [
    path('admin/', admin.site.urls),
    ...,
    path('api-auth/', include('rest_framework.urls')),
    path('', include('some_apps.urls')),
    ...,
    # Put this at the end! This way, Django tries all 
    # its API URLs and if it doesn't find anything it
    # redirects to the frontend
    path('', include('frontend.urls'))
]

反应前端

// stuff ...

const Page404 = () => 
  return (
    <h3>404 - Not found</h3>
  );
;

class App extends Component 
    render()
        return (
            <Router>
                <Navbar />

                <Switch>
                    // React handles any paths you specify, e.g. within the switch
                    <Route exact path='/some_paths/' component=SomeComponents />
                    // If nothing matches...
                    <Route component=Page404 />
                </Switch>
            </Router>
        )
    


// stuff...

【讨论】:

【参考方案5】:

我可以通过在 React 应用程序中使用 HashRouter 来解决这个问题。这会在 url 的开头添加一个 #,您可以在 Django urls.py 中使用空路径(您的路径将如下所示:example.com/#/about/

Here is a good explanation(别忘了点赞)。

您的文件将如下所示:

App.tsx

<Router>
    <Switch>
        <Route path="/article/:articleID">
            <Article />
        </Route>
        /* your routes */
    </Switch>
</Router>

然后只是一条空路径。 urls.py

urlpatterns = [
    path("", TemplateView.as_view(template_name='index.html'))
]

【讨论】:

以上是关于使用 Django + react-router 找不到 404 页面的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 项目中使用 react-router 处理 404 错误

关于react-router最新版本的使用

[react-router] React-Router怎么获取历史对象?

如何使用 react-router 重新加载页面?

使用带有 react-router 的锚点

React-Router 介绍及使用