GET API showing KeyError in browser, but working in Postman - reactjs

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!

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.

Related

wkhtmltopdf reported an error: Exit with code 1 due to network error: ContentNotFoundError

good day, please im having this error when i click Export to pdf button…………………
‘’’
views.py
#login_required(login_url='loginpage')
#cache_control(no_cache=True, must_rev alidate=True, no_store=True)
def exportToPdf(request, pk):
c = get_object_or_404(candidate, id=pk)
cookies = request.COOKIES
options = {
'page-size': 'Letter',
'encoding': "UTF-8",
'cookie' : [
('csrftoken', cookies ['csrftoken']),
('sessionid', cookies ['sessionid'])
]
}
pdf = pdfkit.from_url('http://127.0.0.1:8000/'+str(c.id), False, options = options)
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-disposition'] = 'attachment; filename=candidate.pdf'
return response
urls.py
path('int:pk/exporttopdf/', views.exportToPdf, name='exporttopdf'),
‘’’

getting google oauth to work with flask, react, postgresql. keep getting internal server error and cors errors

I'm trying to get google oauth to work with flask and react. When I run the server and try to log in, the google sign-in window pops up and immediately closes down and I get an internal server error. in my flask terminal I get this error:
raise MissingCodeError("Missing code parameter in response.")
oauthlib.oauth2.rfc6749.errors.MissingCodeError: (missing_code) Missing code parameter in response.
Any thoughts?
app.py
#app.route('/login', methods=['POST'])
#cross_origin()
def login():
google_provider = get_google_provider()
auth_endpoint = google_provider["authorization_endpoint"]
request_uri = client.prepare_request_uri(
authorization_endpoint,
redirect_uri=request.base_url + "/callback",
scope=["openid", "email", "profile"]
)
return redirect(request_uri)
#app.route('/login/callback', methods=['GET', 'POST'])
#cross_origin()
def login_callback():
code = request.json.get("access token")
print("**************")
# print(list(request.args.keys()))
print(request.json)
print("**************")
token, headers, body = client.prepare_token_request(
token_endpoint,
code=code,
authorization_response=request.url,
redirect_url=request.base_url
)
token_response = requests.post(
token_url,
headers=headers,
data=body,
auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
)
client.parse_request_body_response(json.dumps(token_response.json()))
userinfo_endpoint = google_provider["userinfo_endpoint"]
uri, headers, body = client.add_token(userinfo_endpoint)
userinfo_response = request.get(uri, headers=headers, data=body)
if userinfo_response.json().get("email_verified"):
unique_id = userinfo_response.json()["sub"]
user_email = userinfo_response.json()["email"]
user_picture = userinfo_response.json()["picture"]
user_name = userinfo_response.json()["given_name"]
user_member_since = datetime.today().strftime('%Y-%m-%d')
else:
print("User email not available or not verified by Google")
user = User(id=unique_id, name=user_name, email=user_email, picture=user_picture, member_since=user_member_since)
if not User.get(unique_id):
User.create(unique_id, user_name, user_email, user_picture, user_member_since)
login_user(user)
redirect(url_for("/new-user-form"))
app.js
googleResponse = (response) => {
const tokenBlob = new Blob([JSON.stringify({access_token: response.accessToken}, null, 2)], {type: 'application/json'});
const options = {
method: 'POST',
body: tokenBlob,
mode: 'cors',
cache: 'default'
}
fetch(`${BASE_URL}/login/callback`, options).then(r => {
if (r.headers.get('Content-Type') === 'text/html; charset=utf-8') {
console.log('error')
return
}
const token = r.headers.get('x-auth-token')
r.json().then(user => {
if (token) {
this.setState({isAuthenticated: true, user, token, message: `${user.name}`})
console.log(token)
}
});
})
}
onFailure = (error) => {
alert(error.data)
}
<Route path='/login'>
<GoogleLogin
clientId={config.GOOGLE_CLIENT_ID}
buttonText="Login"
onSuccess={this.googleResponse}
onFailure={this.onFailure}
/>

Angular + Django REST Authentication credentials were not provided

I'm developing an API with Django REST. The client is a SPA in AngularJS running in node.js. Register and Login work fine, but when the user does logout the error message is showed:
{"detail":"Authentication credentials were not provided."}
I tried many solutions, like post 1 and post 2. but the problem continues. If my Angular files are in the server, my page works fine, but when I changed for a SPA created by yeoman, I have the credentials problem.
My settings.py
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'y6u0gy4ij&8uoo6#p*$qukwp$-07#-1gd)#)(l!-j&wmpot4h#'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'authentication',
'corsheaders',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', #
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'ServerLearn.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
)
}
WSGI_APPLICATION = 'ServerLearn.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
AUTH_USER_MODEL = 'authentication.Account'
CORS_ORIGIN_ALLOW_ALL = True
CORS_URLS_REGEX = r'^/api/v1/.*$'
My models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
from django.conf import settings
# Create your models here.
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
token = Token.objects.create(user=instance)
print(token)
class AccountManager(BaseUserManager):
def create_user(self, username, password=None, **kwargs):
if not username:
raise ValueError("Need username.")
if not kwargs.get("email"):
raise ValueError("Need email.")
account = self.model(
username = username,
email = self.normalize_email(kwargs.get("email")),
name = kwargs.get("name"),
age = kwargs.get("age"),
gender = kwargs.get("gender"),
#birth = kwargs.get("birth")
)
account.set_password(password)
account.save()
return account
#admin
#senhaadmin
def create_superuser(self, username, password, **kwargs):
account = self.model(
username = username,
email = self.normalize_email(kwargs.get("email")),
name = "Admin",
age = 31111,
gender = 555,
)
account.is_admin = True
account.set_password(password)
account.save()
return account
class Account(AbstractBaseUser):
username = models.CharField(max_length = 50, unique = True)
email = models.EmailField(unique = True)
name = models.CharField(max_length = 100)
age = models.PositiveSmallIntegerField()
gender = models.PositiveSmallIntegerField()
#birth = models.DateField(null = True, blank = True)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
is_admin = models.BooleanField(default = False)
objects = AccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FILES = ['username', 'email', 'name', 'age', 'gender']
def __unicode__ (self):
return self.username
My views.py
class AccountViewSet(viewsets.ModelViewSet):
lookup_field = 'username'
queryset = Account.objects.all()
serializer_class = AccountSerializer
def get_permissions(self):
if self.request.method in permissions.SAFE_METHODS:
return (permissions.AllowAny(),)
if self.request.method == 'POST':
return (permissions.AllowAny(),)
return (permissions.IsAuthenticated(), IsAccountOwner(),)
def create(self, request):
serializer = self.serializer_class(data = request.data)
if serializer.is_valid():
Account.objects.create_user(**serializer.validated_data)
return Response(serializer.validated_data, status = status.HTTP_201_CREATED)
return Response({
'status': 'Bad request',
'message': 'Conta não pode ser criada'
}, status = status.HTTP_400_BAD_REQUEST)
class LoginView(views.APIView):
def post(self, request, format=None):
data = json.loads(request.body.decode('utf-8'))
username = data.get('username', None)
password = data.get('password', None)
account = authenticate(username=username, password=password)
if account is not None:
if account.is_active:
login(request, account)
serialized = AccountSerializer(account)
return Response(serialized.data)
else:
return Response({
'status': 'Unauthorized',
'message': 'This account has been disabled.'
}, status=status.HTTP_401_UNAUTHORIZED)
else:
return Response({
'status': 'Unauthorized',
'message': 'Username/password combination invalid.'
}, status=status.HTTP_401_UNAUTHORIZED)
class LogoutView(views.APIView):
#ERROR IN NEXT LINE
permission_classes = (permissions.IsAuthenticated,)
def post(self, request, format=None):
logout(request)
return Response({}, status=status.HTTP_204_NO_CONTENT)
In my Angular application, in app.js
app.run(run);
run.$inject = ['$http'];
function run($http) {
$http.defaults.xsrfHeaderName = 'X-CSRFToken';
$http.defaults.xsrfCookieName = 'csrftoken';
}
I get token after login with code:
$http.post('http://localhost:8000/api/v1/api-token-auth/', {
username: username,
password: password
}).then(tokenSuccessFn, tokenErrorFn);
function tokenSuccessFn(data, status, headers, config) {
console.log("token: ");
console.log(JSON.stringify(data));
$http.defaults.headers.common.Authorization = 'Token ' + $cookies.get("csrftoken");
}
function tokenErrorFn(data, status, headers, config) {
console.error('token error !!!');
}
The logout is
return $http.post('http://localhost:8000/api/v1/auth/logout/')
.then(logoutSuccessFn, logoutErrorFn);
function logoutSuccessFn(data, status, headers, config) {
Authentication.unauthenticate();
window.location = '/';
}
function logoutErrorFn(data, status, headers, config) {
console.error('Logout error !!!');
}
remove 'rest_framework.authentication.SessionAuthentication' from your DRF DEFAULT_AUTHENTICATION_CLASSES,only use TokenAuth,if you still need browsable api,you can use chrome plugin ModHeader.
I found the problem. I didn't add the token to header correctly.
I get the token and storage in a local storage.
$http.post('http://localhost:8000/api/v1/api-token-auth/', {
username: username,
password: password
}).then(tokenSuccessFn, tokenErrorFn);
function tokenSuccessFn(data, status, headers, config) {
localStorage.setItem('myApp.token',data['data'].token);
}
function tokenErrorFn(data, status, headers, config) {
console.error('token error !!!');
}
When the app (page) begins, I load the token from local storage in app.js:
app.run(['$http', function ($http) {
$http.defaults.headers.common['Authorization'] = 'Token ' + localStorage.getItem('myApp.token');
}]);
Thanks Ykh for the help.

serializer.is_valid() = false when posting an object from AngularJS frontend to Django backend

I have an AngularJS front-end and a Django backend.
The front-end calls the backend using the following two $http calls:
athleticsApp.controller('athletesListController', ['$scope', '$http', function($scope, $http) {
$scope.athletes = [];
$scope.getAthletes = function(){
$http
.get('http://serverip:8666/athletics/athletes/')
.success(function(result) {
$scope.athletes = result;
})
.error(function(data, status) {
console.log(data);
console.log(status);
});
}
$scope.init = function() {
$scope.getAthletes();
}
$scope.init();
}]);
athleticsApp.controller('athleteNewController', ['$scope', '$http', function($scope, $http) {
$scope.athlete = {
firstName : '',
lastName : ''
};
$scope.postNewAthlete = function(){
$http
.post('http://serverip:8666/athletics/athletes/', $scope.athlete)
.success(function(result) {
// set url fraction identifier to list athletes
})
}
}]);
The GET call is a success. The POST call generates the following error:
400 (BAD REQUEST)
When I run the Python debugger I can see that serializer.is_valid() is false.
(Pdb) serializer = AthleteSerializer(data=request.data)
(Pdb) serializer
AthleteSerializer(data={u'lastName': u'Smith', u'firstName': u'John'}):
first_name = CharField(max_length=30)
last_name = CharField(max_length=30)
(Pdb) serializer.is_valid()
False
The Django code looks like this:
urls.py
from django.conf.urls import patterns, url
from views import Athletes
urlpatterns = [
url(r'^athletes/', Athletes.as_view()),
]
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Athlete
from django.shortcuts import get_object_or_404, render
from athletics.serializers import AthleteSerializer
class Athletes(APIView):
def get(self, request, format=None):
import pdb; pdb.set_trace()
all_athletes = Athlete.objects.all()
serializer = AthleteSerializer(all_athletes, many=True)
return Response(serializer.data)
def post(self, request, format=None):
import pdb; pdb.set_trace()
serializer = AthleteSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
creation_data = serializer.save()
return Response()
def index(request):
return render(request, 'athletics/index.html')
serializers.py
from rest_framework import serializers
from .models import Athlete
class AthleteSerializer(serializers.ModelSerializer):
class Meta:
model = Athlete
fields = (
'first_name',
'last_name'
)
settings.py
"""
Django settings for mysitedjango project.
Generated by 'django-admin startproject' using Django 1.8.5.
For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'secretkey'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
INTERNAL_IPS = (
'myip'
)
CORS_ORIGIN_ALLOW_ALL = True
ALLOWED_HOSTS = []
# Application definition
REQUIRED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third party apps
'rest_framework',
)
PROJECT_APPS = (
# This project
'athletics',
'testetics',
)
INSTALLED_APPS = REQUIRED_APPS + PROJECT_APPS
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'corsheaders.middleware.CorsMiddleware',
)
ROOT_URLCONF = 'mysitedjango.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'mysitedjango.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Europe/Stockholm'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
STATIC_URL = '/static/'

AngularJS rest API call to Django, GET works but POST is forbidden

I have an AngularJS front-end and a Django backend.
The front-end calls the backend using the following two $http calls:
athleticsApp.controller('athletesListController', ['$scope', '$http', function($scope, $http) {
$scope.athletes = [];
$scope.getAthletes = function(){
$http
.get('http://serverip:8666/athletics/athletes/')
.success(function(result) {
$scope.athletes = result;
})
.error(function(data, status) {
console.log(data);
console.log(status);
});
}
$scope.init = function() {
$scope.getAthletes();
}
$scope.init();
}]);
athleticsApp.controller('athleteNewController', ['$scope', '$http', function($scope, $http) {
$scope.athlete = {
firstName : '',
lastName : ''
};
$scope.postNewAthlete = function(){
$http
.post('http://serverip:8666/athletics/athletes/', $scope.athlete)
.success(function(result) {
// set url fraction identifier to list athletes
})
}
}]);
The GET call is a success. The POST call generates the following error:
POST http://serverip:8666/athletics/athletes/ 403 (FORBIDDEN)
Why does it generate an error?
The Django code looks like this:
urls.py
from django.conf.urls import patterns, url
from views import Athletes
urlpatterns = [
url(r'^athletes/', Athletes.as_view()),
]
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Athlete
from django.shortcuts import get_object_or_404, render
from athletics.serializers import AthleteSerializer
class Athletes(APIView):
def get(self, request, format=None):
all_athletes = Athlete.objects.all()
serializer = AthleteSerializer(all_athletes, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = AthleteSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
creation_data = serializer.save()
return Response()
serializers.py
class AthleteSerializer(serializers.ModelSerializer):
class Meta:
model = Athlete
fields = (
'first_name',
'last_name'
)
settings.py
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'characters'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
INTERNAL_IPS = (
'myip'
)
CORS_ORIGIN_ALLOW_ALL = True
ALLOWED_HOSTS = []
# Application definition
REQUIRED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third party apps
'rest_framework',
)
PROJECT_APPS = (
# This project
'athletics',
'testetics',
)
INSTALLED_APPS = REQUIRED_APPS + PROJECT_APPS
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'corsheaders.middleware.CorsMiddleware',
)
ROOT_URLCONF = 'mysitedjango.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'mysitedjango.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Europe/Stockholm'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
STATIC_URL = '/static/'
EDIT: I added settings.py
Add :
#api_view(['POST', 'GET'])
just before your Athletes class.
You need to make sure CSRF is sent if you're using the session based authentication.
Django documentation has a full explanation on how to do it: https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
Note that there must be angular plugins that handles that already though I don't have one to recommend as I'm not using angular for my APIs.
Could you post the full error you are getting?
Django normally tells you why your request was rejected.
If the issue is the CSRF, have a look at:
XSRF headers not being set in AngularJS
which solved the issue I had accessing the django backend.

Resources