1

I have encountered a strange problem where the GET API that I created was working fine in Postman, but not working at that specific URL when entered in the browser.

Here is what the input and output should look like as shown successfully in Postman: Trying API in Postman

Here is what the error is showing on my browser: Error in browser

I am also getting this error in React about CORS headers even though I have added in code to try to handle that issue: Error in React about CORS

  • Here is the code in settings.py in Django:

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

  • Here is the code in local_settings.py in Django:

    #########################################
        ##  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

  • I also tried adding this code in index.js in React to handle the CORS headers problem but it didn't work:

    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}`));

Here is the code in App.js in React:


    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" alt="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;

Here is the code in views.py in Django:


    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)

I really don't know what I am doing as I am just following a bunch of tutorials online so I would love it if anyone can help with resolving the API issue in the browser and the React issue with CORS in the browser as well. Thank you so much!

pplonski
  • 5,023
  • 1
  • 30
  • 34

1 Answers1

0

The problem is that GET request shouldn't have body (it is not specified/supported by axios). See this issue in axios repository: link.

Please do a change from data to params:

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

And access it in DRF like:

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

Your CORS config is OK.

pplonski
  • 5,023
  • 1
  • 30
  • 34
  • Hi there! Thank you so much for responding! So I tried doing both of your suggested methods, but I ended up getting a KeyError in both Postman and the browser. But, when I did it the original way in views.py instead of doing query_params (and keeping params instead of data in index.js), it worked in Postman but not in the browser. – Krishnasai Chalasani Nov 18 '20 at 07:47
  • When I try launching the React server, it is saying that I have a "TypeError: Cannot read property 'prototype' of undefined". If I remove the part for this: app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); next(); }); , the error goes away and I can see the React page, but the CORS error still remains when I try clicking on the button. – Krishnasai Chalasani Nov 18 '20 at 07:49
  • Your CORS is OK. Please comment out all your processing code (recommendation algorith I guess) and please just run GET without any parameters. If you will be able to run GET without any parameters in Postman and in React, then please try to add a parameters to the GET. If it will be working, please add the recommendation algorithm. Fix one problem at a time. It is easier to move forward. If you are interested in Django and ML you can check my tutorial https://deploymachinelearning.com. I'm also working on the Django+React tutorial https://saasitive.com – pplonski Nov 18 '20 at 11:06
  • Please let me know if you fixed it. – pplonski Nov 18 '20 at 11:07
  • Hi there! Thank you! I have done what you said with commenting out the algorithm code and just returning the User_ID, and it does work in Postman and the browser, but not in React as it is still saying "TypeError: Cannot read property 'prototype' of undefined". However, when I put this code "user = request.query_params.get("ID")" in views.py to get the User_ID value, it is not returning anything in Postman. – Krishnasai Chalasani Nov 18 '20 at 21:23
  • Please follow this tutorial https://saasitive.com/tutorial/django-react-boilerplate-saas/ to correctly configure django and react. You can skip login part. – pplonski Nov 19 '20 at 07:52