【问题标题】:How to set up Django and React project without having to deal with CORS?如何在不处理 CORS 的情况下设置 Django 和 React 项目?
【发布时间】:2017-07-27 16:26:49
【问题描述】:

所以我一直在研究一个向 Django REST-API 发送请求的 React 项目。问题是,我似乎无法解决 CORS 的问题。前端与后端完全隔离。为了确保网站正常运行,我需要让 Django 提供前端文件。我不知道从哪里开始,如何设置 Django + React 环境,这样我就不必处理 CORS 问题?

【问题讨论】:

  • 您不能“不必处理 CORS 问题”。这是一个浏览器安全。你必须处理它。你的实际问题是什么?您的 API 是否位于您所服务的 HTML 页面之外的其他域上?
  • 来自 Antoine Pinsard 链接的文档:“在 REST 框架中处理 CORS 的最佳方法是在中间件中添加所需的响应标头。这样可以确保透明地支持 CORS,而无需改变你视图中的任何行为。”
  • @AntoinePinsard,但是如果我让 Django 提供前端文件,我就不必处理它了,对吧?那不是同一个起源吗?
  • 阅读此blog post

标签: django reactjs


【解决方案1】:

我可以通过将 django 与 react 松散耦合来做到这一点。像这样工作:我在应用程序内的一个文件夹中使用 webpack 启动了一个新的 npm 项目,我需要反应前端(my_app/react_frontend)。所以我在这个文件夹上构建了我的反应前端,里面有一个 index.html(公共的)。这个 index.html 成为我在主 url (render(index.html)) 上的 views.py 中创建的一个索引视图的模板文件。接下来需要一个django的中间件来处理webpack。我在这里使用这个小库:https://github.com/ezhome/django-webpack-loader。您必须按照此库的文档在 settings.py 和 webpack.config.js 中仔细配置文件夹,例如在模板设置中包含 react_frontend 文件夹。

最后,我在 watch 模式下运行我的 webpack dev-server 和 django dev server 来开发。也就是说,我在 packages.json 中的启动脚本是"start": "./node_modules/.bin/webpack --config webpack.config.js --watch"

这样,我的 react 前端仅在 index.html 上与 django 耦合。所有对后端的 ajax 调用都直接定向到 DRF 视图。我不必以这种方式处理 CORS 问题。 CSFR 问题很简单,因为我只需将 {% csrf_token %} 放在 index.html 文件中。 我希望这有帮助。

【讨论】:

    【解决方案2】:

    我处理它的方式(也是用 DJANGO 编写的后端)是我的 react 应用程序使用 NodeJs 进行服务器端渲染和转发 api 请求。这允许我将 Node 服务器上的请求转发到 django 服务器。

    看看这个 nodejs - express 服务器实现:

    import path from 'path'
    import express from 'express'
    import compression from 'compression'
    import React from 'react'
    import { renderToString } from 'react-dom/server'
    import { match, RouterContext } from 'react-router'
    import configureStore from 'data/redux/store';
    import proxy from 'http-proxy-middleware';
    import { Provider } from 'react-redux';
    import { IntlProvider } from 'react-intl';
    import routes from './routes';
    
    const store = configureStore();
    const app = express();
    app.use(compression());
    
    //template engine
    app.set('view engine', 'ejs');
    //where to look for templates
    app.set('views', path.join(__dirname, '/public'));
    //Serve static files
    app.use(express.static(path.join(__dirname, '/public'), { index: false }));
    
    //middleware for handling api request
    app.use('/api/*', proxy({
        target: process.env.API_HOST,
        pathRewrite: { '^/api/': '' },
        changeOrigin: true,
        secure: false,
    }));
    
    app.use('/media/*', proxy({
        target: process.env.API_HOST,
        changeOrigin: true,
        secure: false,
    }));
    
    app.get('*', (req, res) => {
        match({ routes: routes(store), location: req.url }, (err, redirect, props) => {
            if (err) {
                res.status(500).send(err.message)
            } else if (redirect) {
                res.redirect(redirect.pathname + redirect.search)
            } else if (props) {
                const appHtml = renderToString(
                    <Provider store={store}>
                        <IntlProvider locale="en">
                            <RouterContext store={store} {...props} />
                        </IntlProvider>
                    </Provider>
                );
                res.render('index', { appHtml });
            } else {
                res.status(404).send('Not Found')
            }
        })
    });
    
    const PORT = process.env.PORT || 8080;
    app.listen(PORT, function () {
        console.log('Production Express server running at localhost:' + PORT)
    });
    

    所以我有 NodeJS 服务器,它服务器响应应用程序并处理以 /api/ 开头的传入请求,方法是将它们转发到 django 服务器并将响应返回给客户端。

    【讨论】:

    猜你喜欢
    • 2020-05-18
    • 2018-06-08
    • 2021-06-17
    • 2018-06-08
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2021-08-06
    • 2016-01-15
    相关资源
    最近更新 更多