【问题标题】:Django Rest Framework + React rest hooks CORS errorDjango Rest Framework + React rest hooks CORS 错误
【发布时间】:2021-04-26 21:37:08
【问题描述】:

我正在尝试同时集成 React 前端和 Django & DRF 后端。

我正在使用rest-hooks 来获取数据。 只有在资源中定义 urlRoot = 'api/somemodel' 时才会出现 CORS 错误。 但是每当我定义urlRoot = 'api/somemodel.json'(将.json 添加到资源urlRoot)时,我都会从API 中获取数据。

CategoryResource.ts

import { Resource } from '@rest-hooks/rest';
import { API_URL } from '../utils/server';

export default class CategoryResource extends Resource {
    readonly id: number | undefined = undefined;
    readonly name: string = '';
    readonly description: string = '';

    pk() {
        return this.id?.toString();
    }

    static urlRoot = API_URL + 'categories.json';
}

以上代码仅适用于useResource(CategoryResource.list(), {}),但是,每当我使用useResource(CategoryResource.detail(), { id }) 获取一个类别时,由于URL 格式:http://localhost:8000/api/categories.json/1,它会返回一些网络错误。但应该是categories/1.json

所以,我想,如果我能够在向http://localhost:8000/api/categories 发送请求时使用 Postman 以 JSON 格式获取所有类别,我应该使用它,但后来我收到了 CORS 错误。

CORS 配置

我的 Django 配置允许来自settings.py:CORS_ALLOW_ALL_ORIGINS = True 的所有来源。同样,它确实适用于第一种方法。但无论如何,这是我在 Python 中的配置文件:

INSTALLED_APPS = [
    ...
    'rest_framework',
    ...
    'django_filters',
]

MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
]

# CORS // I have tried switching all of these
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True

# CORS_ALLOWED_ORIGINS = [
#     'http://localhost:3000',
# ]

【问题讨论】:

  • 首先你不应该在你的请求地址中使用.json。您能否也解释一下您问题的最后一部分?当您在本地计算机上执行 CORS_ALLOW_ALL_ORIGINS 时,它只能工作,而 url 中没有 .json
  • 您是否正确配置了 cors?像 cors 中间件等。你能用你的 django 应用程序中的 CORS 相关设置更新你的问题吗?
  • 我认为没有必要,因为我已经可以获取数据了。
  • @SadanA。但无论如何,我将它添加到问题中。
  • 你在settings.py中添加了这个吗ALLOWED_HOSTS = ['*']

标签: reactjs django typescript rest django-rest-framework


【解决方案1】:

我只是在urlRoot 和前端的所有其他 URL 上附加了一个斜杠,它就起作用了。不再出现 CORS 错误。

CategoryResource.ts

import { Resource } from '@rest-hooks/rest';
import { API_URL } from '../utils/server';

export default class CategoryResource extends Resource {
    readonly id: number | undefined = undefined;
    readonly name: string = '';
    readonly description: string = '';

    pk() {
        return this.id?.toString();
    }

    static urlRoot = API_URL + 'categories/';
}

其他网址

const category = useResource(CategoryResource.detail(), { id: query.get('category') + '/' });

我想它现在可以正常工作,但不是解决方案。

【讨论】:

    【解决方案2】:

    您应该尝试corsheaders 如下所示...只是另一种方法..

    你应该像这样设置你的配置

    首先安装corsheaders

    $ pip install corsheaders
    

    然后修改settings.py

    INSTALLED_APPS = [
    ..
    'corsheaders', # To Connect API with React App. 
    ]
    

    在 CommonMiddleware 正上方添加这一行

    MIDDLEWARE = [
        ...
        'corsheaders.middleware.CorsMiddleware', #this one
        'django.middleware.common.CommonMiddleware',
        ...
    ]
    

    还有这几行

    CORS_ALLOWED_ORIGINS = [
        "https://example.com",
        "https://sub.example.com",
        "http://localhost:8080",
        "http://localhost:3000",
        "http://127.0.0.1:9000"
    ]
    

    并在 React 应用程序中连接。使用 "axios": "^0.21.1", 来填充请求。 代码应该是这样的......

    用你喜欢的名字创建一个目录,在这种情况下我想命名服务 然后我将添加两个名为 Services.js 和 RestDataSource.js 的文件

    //services.js
    export const baseURL = "http://localhost:8000/";
    export const headers = {
      "Content-type": "application/json",
    };
    

    //RestDataSource.js
    import Axios from "axios";
    
    export class RestDataSource {
      constructor(base_url) {
        this.BASE_URL = base_url;
      }
      GetData(callback) {
        this.SendRequest("get", this.BASE_URL, callback);
      }
      async SendRequest(method, url, callback) {
        callback(
          (
            await Axios.request({
              method: method,
              url: url,
            })
          ).data
        );
      }
    

    }

    在组件中合并您的数据...

    //fileName.js 
    import React, { Component } from "react";
    import { RestDataSource } from "./services/RestDataSource";
    
    export class IsolatedTable extends Component {
      constructor(props) {
        super(props);
        this.state = {
          products: [],
        };
        this.dataSource = new RestDataSource(
          "http://localhost:8000/api/somemodel"
        );
      }
      render() {
        return (
          <table className="table table-sm table-striped table-bordered">
            <thead>
              <tr>
                <th colSpan="5" className="bg-info text-white text-center h4 p-2">
                  (Isolated) Category
                </th>
              </tr>
              <tr>
                <th>model name</th>
    
                <th></th>
              </tr>
            </thead>
            <tbody>
              {this.state.products.map((p) => (
                <tr key={p.id}>
                  {/* <td>{p.id}</td> */}
                  <td>{p.title}</td>
    
                  <td />
                </tr>
              ))}
            </tbody>
          </table>
        );
      }
      componentDidMount() {
        this.dataSource.GetData((data) => this.setState({ products: data }));
      }
    }
    

    在最后导入你想要的组件......这肯定会工作..我也在使用这种方法你可以检查这个 git repo https://github.com/faisalnazik/Django-REST-framework-React.JS-Typescript.git

    【讨论】:

      猜你喜欢
      • 2019-08-02
      • 2016-09-09
      • 2019-11-22
      • 2015-02-13
      • 2016-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多