Django Management Command Not Triggering API Update in Frontend: Debugging Connection Issues Between Django Backend and React Frontend
from django.core.management.base import BaseCommand
from myapi.models import StrengthWknes, CustomUser
import pandas as pd
from sklearn.neighbors import NearestNeighbors
from sklearn.linear_model import LinearRegression
import numpy as np
class Command(BaseCommand):
help = 'Create study groups based on normalized percentages using k-NN and predict target score for the weakest subject'
def add_arguments(self, parser):
parser.add_argument('grade', type=str, help='Grade for which to create study groups')
parser.add_argument('current_user_id', type=int, help='ID of the current user')
parser.add_argument('n_neighbors', type=int, default=5, help='Number of neighbors to find')
def handle(self, *args, **kwargs):
grade = kwargs['grade']
current_user_id = kwargs['current_user_id']
n_neighbors = kwargs['n_neighbors']
user_data = self.fetch_user_data(grade)
group_usernames, group_df = self.create_study_group(user_data, current_user_id, n_neighbors)
if len(group_usernames) < 3:
self.stdout.write(self.style.WARNING('Group is too small. Select group manually.'))
else:
self.stdout.write(self.style.SUCCESS(f'Created group: {group_usernames}'))
# Predict target score for the weakest subject
if not group_df.empty:
target_scores = self.predict_target_score(group_df, current_user_id)
self.stdout.write(self.style.SUCCESS(f'Target scores for the weakest subject: {target_scores}'))
def fetch_user_data(self, grade):
records = StrengthWknes.objects.filter(grade__grade=grade)
data = []
for record in records:
user = CustomUser.objects.get(pk=record.id.id)
data.append({
'user_id': user.id,
'username': user.username,
'normalized_percentage': record.normalized_percentage,
'strgth_wkness': record.strgth_wkness
})
df = pd.DataFrame(data)
self.stdout.write(self.style.SUCCESS(f'Fetched user data:\n{df}'))
return df
def create_study_group(self, df, current_user_id, n_neighbors):
TOLERANCE = 10 # Tolerance percentage range for neighbor selection
MAX_DIFF = 10 # Maximum allowed difference within the group
if len(df) < n_neighbors:
return [], pd.DataFrame() # Return empty group and DataFrame
df['normalized_percentage'] = df['normalized_percentage'].astype(float)
# Prepare data for k-NN
X = df[['normalized_percentage']].values
current_user = df[df['user_id'] == current_user_id]
if current_user.empty:
return [], pd.DataFrame()
current_user_percentage = current_user['normalized_percentage'].values.reshape(1, -1)
# Initialize and fit the k-NN model
knn = NearestNeighbors(n_neighbors=n_neighbors, metric='euclidean')
knn.fit(X)
# Find nearest neighbors
distances, indices = knn.kneighbors(current_user_percentage)
# Get the neighbors
neighbor_indices = indices.flatten()
group_df = df.iloc[neighbor_indices]
# Ensure the current user is included
if current_user_id not in group_df['user_id'].values:
group_df = pd.concat([group_df, current_user])
# Filter out users based on TOLERANCE and MAX_DIFF
current_user_percentage = current_user['normalized_percentage'].values[0]
group_df = group_df[(
(group_df['normalized_percentage'] - current_user_percentage).abs() <= MAX_DIFF
)]
def within_tolerance(row, group_df):
return all(
abs(row['normalized_percentage'] - other['normalized_percentage']) <= TOLERANCE
for _, other in group_df.iterrows()
)
group_df = group_df[group_df.apply(lambda row: within_tolerance(row, group_df), axis=1)]
# If the group is too small, attempt to add more users
while len(group_df) < n_neighbors:
additional_users = df[~df['user_id'].isin(group_df['user_id'])]
additional_users = additional_users[(
(additional_users['normalized_percentage'] - current_user_percentage).abs() <= MAX_DIFF
)]
if additional_users.empty:
break
# Re-check tolerance for additional users
def is_tolerant(row, group_df):
return within_tolerance(row, group_df)
additional_users = additional_users[additional_users.apply(lambda row: is_tolerant(row, group_df), axis=1)]
if not additional_users.empty:
group_df = pd.concat([group_df, additional_users.head(1)])
group_usernames = group_df['username'].tolist()
# Fetch and display the strgth_wkness JSON data for all users in the group
group_ids = group_df['user_id'].tolist()
strgth_wkness_data = StrengthWknes.objects.filter(id__in=group_ids)
strgth_wkness_dict = {user.id: user.strgth_wkness for user in strgth_wkness_data}
self.stdout.write(self.style.SUCCESS(f'Group formation:\n{group_df}'))
self.stdout.write(self.style.SUCCESS(f'Created group: {group_usernames}'))
self.stdout.write(self.style.SUCCESS(f'Strengths and weaknesses of users in the group:\n{strgth_wkness_dict}'))
return group_usernames, group_df
def predict_target_score(self, group_df, current_user_id):
# Identify the current user's data
current_user = group_df[group_df['user_id'] == current_user_id]
if current_user.empty:
return {'message': 'Current user not found in the group.'}
# Fetch current user's strengths and weaknesses
strgth_wkness = current_user['strgth_wkness'].iloc[0]
print("Current user strengths and weaknesses:", strgth_wkness)
# Check if all scores are the same
unique_scores = set(strgth_wkness.values())
if len(unique_scores) == 1:
return {'message': 'All subjects have the same score. Focus on overall improvement.'}
# Find the weakest subject for the current user
weakest_subject = min(strgth_wkness, key=lambda k: strgth_wkness[k])
weakest_subject_scores = [
user['strgth_wkness'].get(weakest_subject, 0) for _, user in group_df.iterrows()
]
# Debug: Log the weakest subject and its scores
print(f"Weakest subject: {weakest_subject}")
print("Weakest subject scores:", weakest_subject_scores)
if not weakest_subject_scores:
return {'message': 'No scores available for the weakest subject.'}
# Prepare data for regression
X_train = np.array(range(len(weakest_subject_scores))).reshape(-1, 1) # Indexes as feature
y_train = np.array(weakest_subject_scores)
# Create and train the model
model = LinearRegression()
model.fit(X_train, y_train)
# Predict the target score for the current user
current_user_index = len(weakest_subject_scores) # Index for prediction
predicted_score = model.predict(np.array([[current_user_index]]))
target_score = round(predicted_score[0])
# Adjust target score if it is lower than current user's score
current_score = strgth_wkness[weakest_subject]
if target_score <= current_score:
target_score = min(current_score + 1, 5) # Ensure target score does not exceed maximum
# Suggest the group member with the highest score in the weakest subject
higher_scores = [score for score in weakest_subject_scores if score > current_score]
if higher_scores:
highest_score_index = weakest_subject_scores.index(max(higher_scores))
suggested_partner = group_df['username'].tolist()[highest_score_index]
else:
suggested_partner = 'No suggestion available, consider focusing on the weakest subject.'
# Return the target score and the suggested partner
return {
'weakest_subject': weakest_subject,
'target_score': target_score,
'suggested_partner': suggested_partner
}
from django.urls import path
from .views import signup, ObtainTokenView, get_subjects_by_grade, save_strengths_weaknesses, get_str_wkn, check_strength_status,update_strength_status,run_create_groups_command
urlpatterns = [
path('signup/', signup, name='signup'),
path('login/', ObtainTokenView.as_view(), name='token_obtain_pair'),
path('subjects/', get_subjects_by_grade, name='get_subjects_by_grade'),
path('save-strengths-weaknesses/', save_strengths_weaknesses, name='save-strengths-weaknesses'),
path('get_str_wkn/', get_str_wkn, name='get_str_wkn'),
path('check-strength-status/',check_strength_status, name='check_strength_status'),
path('update-strength-status/', update_strength_status, name='update_strength_status'),
path('run-create-groups/', run_create_groups_command, name='run_create_groups'),
]
import React, { useState, useEffect } from 'react';
import { jwtDecode } from 'jwt-decode'; // Adjusted import
import axios from 'axios';
import '../css/MakeGroup.css'; // Adjust the path as necessary
const MakeGroup = () => {
const [decodedToken, setDecodedToken] = useState(null);
const [message, setMessage] = useState('');
const [error, setError] = useState('');
const [currentUserId, setCurrentUserId] = useState('');
const [grade, setGrade] = useState('');
useEffect(() => {
const storedToken = localStorage.getItem('token');
if (storedToken) {
try {
const decoded = jwtDecode(storedToken); // Use named import
setDecodedToken(decoded);
setCurrentUserId(decoded.user_id);
setGrade(decoded.grade);
} catch (error) {
console.error('Error decoding token:', error);
}
}
}, []);
const handleCreateGroups = () => {
if (!currentUserId || !grade) {
setError('Error: Missing user information.');
return;
}
console.log('Sending request with:', { current_user_id: currentUserId, grade });
axios.post('http://localhost:8000/api/run-create-groups/',
{ current_user_id: currentUserId, grade },
{
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`
}
}
)
.then(response => {
setMessage(response.data.message);
})
.catch(error => {
setError(error.response ? error.response.data.error : error.message);
});
};
console.log('MakeGroup component rendered!');
return (
<div className="make-group-wrapper">
<div className="make-group-container">
<h2 className="make-group-heading">Create Study Groups</h2>
<button className="create-groups-button" onClick={handleCreateGroups}>
Create Groups
</button>
{message && <p className="message-text">{message}</p>}
{error && <p className="error-text">{error}</p>}
</div>
</div>
);
};
export default MakeGroup;
Running the Django Management Command:
I executed a custom Django management command that fetches user data, creates study groups using k-NN, and predicts target scores based on the weakest subject. The command worked as expected when run via the Django shell, providing the correct user data, forming groups, and calculating target scores. Integration with Frontend:
I attempted to trigger this functionality from the React frontend by making a GET request to the Django API endpoint designed to create study groups based on user data. The API call worked correctly, and the backend provided the expected response when tested with tools like curl or requests. What I Was Expecting:
I expected that triggering the management command from the React frontend via the API would properly execute the group creation logic in the backend and reflect the changes in the frontend. Specifically, I anticipated seeing updates in the React application that would indicate successful group formation and the predicted target scores. Current Issue:
The Django management command runs correctly in isolation, but when trying to connect it with the React frontend through the API, the frontend does not receive the expected updates or reflect changes based on the backend processing.
! curl -X GET "http://localhost:8000/api/run-create-groups/?current_user_id=93&grade=8"
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzI1ODAzNTgxLCJpYXQiOjE3MjU3OTk5ODEsImp0aSI6IjI1MTVmMTU2NTE5NjQwNjZhMGE1M2UwMjhjYTNlMjU0IiwidXNlcl9pZCI6OTMsImVtYWlsIjoiYXJ5YW5AZ21haWwuY29tIiwidXNlcm5hbWUiOiJBcnlhbiIsImdyYWRlIjoiOCIsInN0YXRlIjoiTWl6b3JhbSJ9.VZ4Xgu31CNDNSgwOm63BYOhcrmSmh8nLNM9DLnJgK2A"