My Django endpoints are not allowing Frotnend to access the data
So I'm totally lost. Hobby coder. I am making a web-app where I have got Django dealing with my backend, and react on the frontend. The Django server runs on localhost:8000 and the forntend on localhost:3000. On login, the user is forwarded to the homepage which immediatley requests data from the django rest api to poulate some data on the homepage.
SESSION_ENGINE = "django.contrib.sessions.backends.db"
SESSION_COOKIE_DOMAIN = '.localhost'
SESSION_COOKIE_PATH = "/"
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'api',
'uauth',
'corsheaders',
]
MIDDLEWARE = [
'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',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
}
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
ROOT_URLCONF = 'backend.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
BASE_DIR / 'backend' / 'templates',
BASE_DIR / 'uauth' / 'templates'
],
'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 = 'backend.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/4.1/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/4.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
AUTH_USER_MODEL = 'auth.User'
'''Login View (in the "uath" django app
frontend_url = 'http://localhost:3000'
def loginView(request):
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
response = redirect(frontend_url)
response.set_cookie(key='sessionid', value=request.session.session_key, max_age=3600)
return response
else:
form = AuthenticationForm()
return render(request, 'uauth/login.html', {'form': form})
'''endpoint view in the "api" django app
@permission_classes(['rest_framework.permissions.IsAuthenticated'])
@authentication_classes([SessionAuthentication])
@api_view(['GET'])
def get_user_paddocks(request):
print(request.session)
print(request.data)
paddock_dict = {}
paddock_dict[request.user.username] = {}
paddock_dict[request.user.username]['paddocks'] = {}
user_paddocks_qset = user_paddocks.objects.filter(user = request.user)
for i in range(user_paddocks_qset.count()):
paddock_user_qset = user_paddocks.objects.filter(paddock = user_paddocks_qset[i].paddock)
paddock_dict[request.user.username]['paddocks'][user_paddocks_qset[i].paddock.paddock_name] = {
"name" : user_paddocks_qset[i].paddock.paddock_name,
'user_count': paddock_user_qset.count(),
}
paddock_dict[request.user.username]['paddocks'][user_paddocks_qset[i].paddock.paddock_name]['users'] = []
for u in range(paddock_user_qset.count()):
paddock_dict[request.user.username]['paddocks'][user_paddocks_qset[i].paddock.paddock_name]['users'].append(paddock_user_qset[u].user.username)
print(request.user.username + " is requesting thier paddock data")
return Response(paddock_dict)
HomePage.js
import React, { useState, useEffect } from "react";
import axios from "axios";
const HomePage = () => {
const [paddocksData, setPaddocksData] = useState(null);
const [error, setError] = useState(null);
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
useEffect(() => {
axios
.get("http://127.0.0.1:8000/api/user-paddocks", { withCredentials: true })
.then(res => {
console.log('API response: ', res.data);
setPaddocksData(res.data);
})
.catch(err => setError(err.message));
}, []);
if (error) {
return <div>Error: {error}</div>;
}
if (!paddocksData) {
return <div>Loading...</div>;
}
const username = Object.keys(paddocksData)[0];
const userPaddocks = paddocksData[username].paddocks;
const { paddocks } = paddocksData;
console.log(paddocksData)
const paddockCount = Object.keys(paddocks).length;
if (paddockCount === 0) {
return (
<div>
<p>Looks like you aren't part of any paddocks yet, let's get you going.</p>
<button>Create Paddock</button>
<button>Join Paddock</button>
</div>
);
}
const singleUserPaddocks = Object.values(paddocks).filter(
paddock => paddock.user_count === 1
);
const singleUserPaddockCount = singleUserPaddocks.length;
if (singleUserPaddockCount === paddockCount) {
return (
<div>
<p>Looks like you don't have anyone to play against, let's invite some</p>
<input placeholder="Enter email addresses" />
<button>Invite</button>
</div>
);
}
return (
<div>
<p>Deadlines for all predictions for your paddocks:</p>
{Object.values(paddocks).map(paddock => (
<div key={paddock.name}>
<p>Paddock: {paddock.name}</p>
<p>Deadline: [Insert deadline here]</p>
</div>
))}
</div>
);
};
export default HomePage;
After login, the user is redirected to the Homepage correctly, but this is the error message on the backend server: [01/Feb/2023 13:40:28] "GET /uauth/login/ HTTP/1.1" 200 855 [01/Feb/2023 13:40:30] "POST /uauth/login/ HTTP/1.1" 302 0 Forbidden: /api/user-paddocks [01/Feb/2023 13:40:31] "GET /api/user-paddocks HTTP/1.1" 403 58
Please let me know what needs to be done here. Many Thanks
I tried to add autehtication and session variables to the setting.py to try persist the session and request data after the login happens. It seems to me the request object is empty when the hompage tries to make the api call