GET API 在浏览器中显示 KeyError,但在 Postman 中工作

Posted

技术标签:

【中文标题】GET API 在浏览器中显示 KeyError,但在 Postman 中工作【英文标题】:GET API showing KeyError in browser, but working in Postman 【发布时间】:2021-03-01 02:43:57 【问题描述】:

我遇到了一个奇怪的问题,我创建的 GET API 在 Postman 中运行良好,但在浏览器中输入时无法在该特定 URL 上运行。

下面是 Postman 中成功显示的输入和输出的样子:Trying API in Postman

这是我的浏览器上显示的错误:Error in browser

我在 React 中也遇到了这个关于 CORS 标头的错误,即使我已经添加了代码来尝试处理这个问题:Error in React about CORS

这是 Django 中 settings.py 中的代码:

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'Prediction',
        'rest_framework',
        'corsheaders',
    ]
    
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

这是 Django 中 local_settings.py 中的代码:

    #########################################
        ##  IMPORT LOCAL SETTINGS ##
    #########################################
    
    try:
        from .local_settings import *
    except ImportError:
        pass
    
    DATABASES = 
        'default': 
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'postgres',
            'USER': 'postgres',
            'PASSWORD': 'postgres',
            'HOST': '127.0.0.1',
            'PORT': '5432',
        
    
    
    #################################################################
        ##  (CORS) Cross-Origin Resource Sharing Settings ##
    #################################################################
    CORS_ORIGIN_ALLOW_ALL = True

我还尝试在 React 中的 index.js 中添加此代码来处理 CORS 标头问题,但它不起作用:

    const express = require('express');
    const request = require('request');
    
    const app = express();
    
    app.use((req, res, next) => 
        res.header('Access-Control-Allow-Origin', '*');
        next();
    );
    
    app.get('/jokes/random', (req, res) => 
        request(
                url: 'https://joke-api-strict-cors.appspot.com/jokes/random'
            ,
        (error, response, body) => 
            if (error || response.statusCode !== 200) 
                return res.status(500).json(
                    type: 'error',
                    message: err.message
                );
            
    
            res.json(JSON.parse(body));
        
    )
    );
    
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => console.log(`listening on $PORT`));

这是 React 中 App.js 中的代码:


    import logo from './logo.svg';
    import './App.css';
    import  useState  from 'react';
    import axios from 'axios';
    
    function App() 
        const [json_response1, set_json_response1] = useState("1st algorithm - List of similar events");
    
        function request_json_response() 
            axios.get('http://127.0.0.1:8000/api/get_events_1st_alg', 
                    data: 
                        "ID": "User_ID1"
                    
                ).then(function (response) 
                    // handle success
                    set_json_response1(response);
                );
        
    
        return (
            <div className="App">
                <header className="App-header">
                    <img src=logo className="App-logo"  />
                        <p>
                            json_response1
                        </p>
    
                    <button onClick=request_json_response>
                        Generate events for user
                    </button>
    
                    <a
                        className="App-link"
                        href="https://reactjs.org"
                        target="_blank"
                        rel="noopener noreferrer"
                    >
                        Learn React
                    </a>
            </header>
        </div>
    );
    
    
    export default App;

这是 Django 中的 views.py 中的代码:


    class get_events_1st_alg(APIView):
        def get(self, request, format=None):
            """
            data = request.data
            banana_dictionary = 'banana':17
            return Response(banana_dictionary, status=status.HTTP_201_CREATED)
            """
            import pandas as pd
            import numpy as np
            import psycopg2
            import sqlalchemy
            from sklearn.metrics.pairwise import cosine_similarity
            from sklearn.metrics import pairwise_distances
            import requests
    
            from sqlalchemy import create_engine
            engine = create_engine('postgresql://postgres:postgres@localhost/postgres')
            # pd.read_sql_query('''SELECT * FROM arts_user_interaction LIMIT 5;''', engine)
            events = pd.read_sql_query('''SELECT * FROM arts_event;''', engine)
            Ratings = pd.read_sql_query('''SELECT * FROM arts_user_interaction;''', engine)
    
            Mean = Ratings.groupby(by="User_ID", as_index = False)['User Rating'].mean()
            Rating_avg = pd.merge(Ratings, Mean, on = "User_ID")
            Rating_avg['adg_rating']=Rating_avg['User Rating_x']-Rating_avg['User Rating_y']
    
            check = pd.pivot_table(Rating_avg,values='User Rating_x',index='User_ID',columns='Event_ID')
            final = pd.pivot_table(Rating_avg,values='adg_rating',index='User_ID',columns='Event_ID')
            final_event = final.fillna(final.mean(axis=0))
            final_user = final.apply(lambda row: row.fillna(row.mean()), axis=1)
    
            cosine = cosine_similarity(final_event)
            np.fill_diagonal(cosine, 0 )
            similarity_with_event =pd.DataFrame(cosine,index=final_event.index)
            similarity_with_event.columns=final_user.index
    
            def find_n_neighbours(df,n):
                order = np.argsort(df.values, axis=1)[:, :n]
                df = df.apply(lambda x: pd.Series(x.sort_values(ascending=False)
                       .iloc[:n].index, 
                      index=['top'.format(i) for i in range(1, n+1)]), axis=1)
                return df
    
            sim_user_30_e = find_n_neighbours(similarity_with_event,30)
    
            def get_user_similar_events( user1, user2 ):
                common_events = Rating_avg[Rating_avg.User_ID == user1].merge(
                Rating_avg[Rating_avg.User_ID == user2],
                on = "Event_ID",
                how = "inner" )
                return common_events.merge(events, on ='Event_ID')
    
            a = get_user_similar_events('User_ID10','User_ID220')
            a = a.reindex(columns= ['User Rating_x_x','User Rating_x_y','Name'])
    
            Rating_avg = Rating_avg.astype("Event_ID": str)
            Movie_user = Rating_avg.groupby(by = 'User_ID')['Event_ID'].apply(lambda x:','.join(x))
    
            def User_item_score1(user):
                Movie_seen_by_user = check.columns[check[check.index==user].notna().any()].tolist()
                a = sim_user_30_e[sim_user_30_e.index==user].values
                b = a.squeeze().tolist()
                d = Movie_user[Movie_user.index.isin(b)]
                l = ','.join(d.values)
                Movie_seen_by_similar_users = l.split(',')
                Movies_under_consideration = list(set(Movie_seen_by_similar_users)-set(list(map(str, Movie_seen_by_user))))
                Movies_under_consideration = list(map(str, Movies_under_consideration))
                score = []
                for item in Movies_under_consideration:
                    c = final_event.loc[:,item]
                    d = c[c.index.isin(b)]
                    f = d[d.notnull()]
                    avg_user = Mean.loc[Mean['User_ID'] == user,'User Rating'].values[0]
                    index = f.index.values.squeeze().tolist()
                    corr = similarity_with_event.loc[user,index]
                    fin = pd.concat([f, corr], axis=1)
                    fin.columns = ['adg_score','correlation']
                    fin['score']=fin.apply(lambda x:x['adg_score'] * x['correlation'],axis=1)
                    nume = fin['score'].sum()
                    deno = fin['correlation'].sum()
                    final_score = avg_user + (nume/deno)
                    score.append(final_score)
                data = pd.DataFrame('Event_ID':Movies_under_consideration,'score':score)
                top_5_recommendation = data.sort_values(by='score',ascending=False).head(5)
                Movie_Name = top_5_recommendation.merge(events, how='inner', on='Event_ID')
                Movie_Names = Movie_Name.Name.values.tolist()
                return Movie_Names
    
            # user = input("Enter the user id to whom you want to recommend : ")
            data = request.data
    
            user = ""
    
            for i, v in data.items():
                user = str(v)
    
            predicted_movies = User_item_score1(user)
    
            return Response(predicted_movies, status=status.HTTP_201_CREATED)

我真的不知道我在做什么,因为我只是在网上学习一堆教程,所以如果有人可以帮助解决浏览器中的 API 问题和浏览器中的 CORS 的 React 问题,我会很高兴的好吧。非常感谢!

【问题讨论】:

【参考方案1】:

问题是 GET 请求不应该有正文(它没有被 axios 指定/支持)。在 axios 存储库中查看此问题:link。

请从数据更改为参数:

axios.get('http://127.0.0.1:8000/api/get_events_1st_alg',  params:  "ID":"User_ID1")

并在 DRF 中访问它,例如:

user = request.query_params.get("ID")

您的 CORS 配置正常。

【讨论】:

您好!非常感谢您的回复!所以我尝试了你建议的两种方法,但我最终在邮递员和浏览器中都得到了一个 KeyError 。但是,当我在 views.py 中以原始方式而不是在 index.js 中执行 query_params(并在 index.js 中保留参数而不是数据)时,它在 Postman 中有效,但在浏览器中无效。 当我尝试启动 React 服务器时,它说我有一个“TypeError: Cannot read property 'prototype' of undefined”。如果我为此删除部分: app.use((req, res, next) => res.header('Access-Control-Allow-Origin', '*'); next(); ); ,错误消失了,我可以看到 React 页面,但是当我尝试单击按钮时,CORS 错误仍然存​​在。 您的 CORS 正常。请注释掉你所有的处理代码(我猜是推荐算法),请只运行 GET 而不带任何参数。如果您能够在 Postman 和 React 中不带任何参数运行 GET,那么请尝试向 GET 添加参数。如果它会工作,请添加推荐算法。一次解决一个问题。更容易前进。如果您对 Django 和 ML 感兴趣,可以查看我的教程 deploymachinelearning.com。我也在做 Django+React 教程saasitive.com 如果你修好了请告诉我。 您好!谢谢!我已经完成了您所说的注释算法代码并仅返回 User_ID,它确实在 Postman 和浏览器中工作,但在 React 中不起作用,因为它仍然在说“TypeError:无法读取未定义的属性'原型'”。但是,当我将此代码“user = request.query_params.get("ID")”放入views.py 以获取User_ID 值时,它不会在Postman 中返回任何内容。

以上是关于GET API 在浏览器中显示 KeyError,但在 Postman 中工作的主要内容,如果未能解决你的问题,请参考以下文章

Django:request.GET 和 KeyError

KeyError: 'commentCount' 在 Python 中使用 Youtube API

Google 日历 API:KeyError:“位置”

尝试通过函数参数将正文发送到 API 时出现 KeyError

python里出现keyerror 怎么解决

Facebook graph api keyerror '下一个'