post xlsx file to flask route with React async/await - reactjs

I have a project where I was originally using fetch for all of my requests, and my excel upload function was working fine. I recently made a lot of changes to my application because I added user login and authentication, so I am now trying to reconfigure my routes using async await in React. I am getting different errors that I don't know how to solve. Sometimes when I try to submit the uploaded file I get a 400 error for a bad request, usually saying ""The browser (or proxy) sent a request that this server could not understand.\nKeyError: 'project'". Or I am getting an error on the back-end that says "ValueError: Excel file format cannot be determined, you must specify an engine manually."
I am really confused about where the error is actually occurring because it seems to be reaching the Flask route and then failing.
This is my current request on the front-end:
const onSubmit = async (ev) => {
ev.preventDefault();
let formData = new FormData();
formData.append("project", selectedFile);
// let status = 0;
const data = await api.post("/projects", {
body: formData,
});
if (!data.ok) {
console.log(data);
console.log("error");
} else {
console.log(data);
console.log("uploaded");
}
};
and the back-end route:
#projects.route('/projects', methods=['POST'])
#authenticate(token_auth)
def request_load_pickle_sim():
fn = save_file(None, "project", "xlsx")
print(fn)
request.files["project"].save(fn)
result = process_raw_util_xl_file(fn)
claims = result['claims']
print(claims)
utilities = result['utilities']
weights = result['weights']
maxdiff_scores = result['maxdiff_scores']
data = jsonify(claims)
print(data)
mdp = MaxDiffProject()
mdp.config = MutableDict({
'claims': claims,
'utilities': utilities,
'weights': weights,
'maxdiff_scores': maxdiff_scores
})
print(mdp.config)
db.session.add(mdp)
db.session.commit()
mdp = MaxDiffProject().query.first()
project_config = mdp.config
claims = project_config['claims']
print(claims)
data = jsonify(claims)
return data
My debugger is printing the instance of the file, so it seems like the backend is receiving the file? But after that nothing is working. The file is passed to the process_raw_util_xl_file function (which is where the ValueError error is coming from). I can't figure out what the core issue is because I'm getting conflicting errors. I guess I'm just confused because it was all working fine when I had fetch requests.
The function on the backend is breaking here:
def process_raw_util_xl_file(xl_fn):
# df = pd.read_csv(xl_fn.read())
df = pd.read_excel(xl_fn) # read the excel file
print(df)
row = df.shape[0] # df.shape[0] = Number of rows, df.shape[1] = number of columns
index_col = [col for col in df if 'id' in col.lower()][0]
print(index_col)
df.set_index(index_col, inplace=True) # Setting the ID as the index
# weights = df['Weights'] if 'Weights' in df else pd.Series([1]*row) # Creating the weights array if there are weights , otherwise an array of 1's with # of rows
if 'Weights' not in df:
df['Weights'] = 1
weights = df['Weights']
df.drop('Weights', axis=1, inplace=True)
sum = weights.values.sum() # Sum of the weights
# if 'Weights' in df: df = df.drop('Weights', axis=1) # removing weights from df if they are there
rlh_cols = [col for col in df if 'rlh' in col.lower()][:1]
df = df.drop(rlh_cols, axis=1) # removing RLH from df if they are there
max_diff_scores = (e ** df) / (1 + e ** df) * 100 # exp the values of the dataframe with
utils = df
return {
"utilities": utils,
"claims": [col for col in utils],
"maxdiff_scores": max_diff_scores,
"weights": weights
}

You are posting an object as a body paramter to the server which has a content type as application/json whereas according the HTTP protocol, to post form-data the content type must be multipart/form-data. Here's how you are doing it,
let formData = new FormData();
formData.append("project", selectedFile);
// let status = 0;
const data = await api.post("/projects", {
body: formData,
});
According to the docs (at page end) you must post form data like this,
let formData = new FormData();
formData.append("project", selectedFile);
// let status = 0;
const data = await api.post("/projects", formData);
Also you cannot post body and form data at a same time within single request.

Related

Resource units used for a graph request

I have the following code to find the count of users in AAD group:
var requestUrl = _graphClient.Groups[objectId.ToString()].TransitiveMembers.Request().RequestUrl;
requestUrl = $"{requestUrl}/microsoft.graph.user/$count";
var hrm = new HttpRequestMessage(HttpMethod.Get, requestUrl);
hrm.Headers.Add("ConsistencyLevel", "eventual");
await _graphServiceClient.AuthenticationProvider.AuthenticateRequestAsync(hrm);
var r = await _graphServiceClient.HttpProvider.SendAsync(hrm);
var content = await r.Content.ReadAsStringAsync();
var userCount = int.Parse(content);
return userCount;
Is there a way to find out the resource units used for this request (https://learn.microsoft.com/en-us/graph/throttling-limits)
According to the documentation, the resource unit cost for GET groups/{id}/transitiveMembers is 5.
But using $count affects the cost. If you send the request
GET https://graph.microsoft.com/v1.0/groups/{group_id}/transitivemembers/microsoft.graph.user/$count
and check the response headers there should be header x-ms-resource-unit which indicates the resource unit cost used for this request and it's 1.
Get header x-ms-resource-unit
var r = await _graphServiceClient.HttpProvider.SendAsync(hrm);
var cost = r.Headers.GetValues("x-ms-resource-unit").FirstOrDefault();

irregular arbitrarily Cross-Origin request blocked error in Django on Ionos hosting

I am currently making a quiz project for school. The quiz is supposed to evaluate in the front-end, which works perfectly fine, and after that it should send the information to the backend. The backend should save the details to the database and after that it should send the information back to the front-end. The front-end should show a message with some details about how you performed compared to all the others, the information is gotten from the database.
So, the weird thing about all that is that it works sometimes and sometimes not. If I test it on localhost, the code works perfectly fine. The error only occurs on the Ionos server (I got a hosting contract so I do not have access to the console).
Here is the link to my website: https://tor-netzwerk-seminarfach2024.com/ . If you click on the upper left corner and then on the quiz button, you will get to the quiz. If I look at the console and network analytics, when the error occurs, the following message shows up:
Cross-Origin request blocked: The same source rule prohibits reading
the external resource on https://api. tor-netzwerk-seminarfach2024.
com/apache-test/. (Reason: CORS request failed).
https://api.tor-netzwerk-seminarfach2024.com/apache-test/ is my backend and https://tor-netzwerk-seminarfach2024.com/ is my front-end.
The settings file in Django is not the problem. To make it clear, the error does not occur always. Sometimes you have to go again to the website and try it one a few more times until you get the error.
If I look at the network analytics, then I see that the client request works as usual, but the answer field from the server is completely empty. Let's move on to the weirdest part of all: the Data actually gets saved in the Database, there is just sometimes no response?
It would be way to much for a minimum working product but here is the most important code. If you want to test it you can just visit the link to my Website:https://tor-netzwerk-seminarfach2024.com/
Server side with Django
from rest_framework.response import Response
from .models import Lead
import json
from .serializer import TestingSerializer
def updateDigits():
leadObj = Lead.objects.all()
currentScore = leadObj[0].sumScore; currentRequests = leadObj[0].sumRequests
valueBtnOne = leadObj[0].buttonOne; valueBtnTwo = leadObj[0].buttonTwo;
valueBtnThree = leadObj[0].buttonThree; valueBtnFour = leadObj[0].buttonFour;
valueBtnFive = leadObj[0].buttonFive; valueBtnSix = leadObj[0].buttonSix;
valueBtnSeven = leadObj[0].buttonSeven; valueBtnEight = leadObj[0].buttonEight;
valueBtnNine = leadObj[0].buttonNine;
return [valueBtnOne,valueBtnTwo,valueBtnThree,valueBtnFour,valueBtnFive,valueBtnSix,valueBtnSeven,valueBtnEight,valueBtnNine,currentScore,currentRequests]
#api_view(["POST"])
def home(request):
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
result = body["Result"]
isItRight = body["whichOnesRight"]
ip_adress = get_client_ip(request)
queryset = Lead.objects.all()
if Lead.objects.all().exists():
currentValues = updateDigits()
queryset.update(
sumScore = result + currentValues[9],
sumRequests = 1 + currentValues[10],
buttonOne = currentValues[0] + isItRight[0],
buttonTwo = currentValues[1] + isItRight[1],
buttonThree = currentValues[2] + isItRight[2],
buttonFour = currentValues[3] + isItRight[3],
buttonFive = currentValues[4] + isItRight[4],
buttonSix = currentValues[5] + isItRight[5],
buttonSeven = currentValues[6] + isItRight[6],
buttonEight = currentValues[7] + isItRight[7],
buttonNine = currentValues[8] + isItRight[8],
)
currentValues = updateDigits()
else:
obj = Lead()
obj.save()
serializer = TestingSerializer(queryset[0], many =False)
return Response({**serializer.data, "myResult": result})
The Django model
from django.db import models
class Lead(models.Model):
sumScore = models.IntegerField(default=0)
sumRequests = models.IntegerField(default=0)
buttonOne = models.IntegerField(default=0)
buttonTwo = models.IntegerField(default=0)
buttonThree = models.IntegerField(default=0)
buttonFour = models.IntegerField(default=0)
buttonFive = models.IntegerField(default=0)
buttonSix = models.IntegerField(default=0)
buttonSeven = models.IntegerField(default=0)
buttonEight = models.IntegerField(default=0)
buttonNine = models.IntegerField(default=0)
serializer just serializes _ _ all _ _ ...
Front end with React
function evaluateAndCheckQuiz(){
let countNotChosen = howManyNotChosen()
if(countNotChosen){ answerQuestions(countNotChosen); return }
let points = evaluateQuiz()
document.getElementById("scoreText").style.display = "block"
document.getElementById("scoreNumber").textContent = points
return points
}
Calling sendAndGetQuizAverage with evaluateAndCheckQuiz as a parameter
function sendAndGetQuizAverage(points){
const myPostRequest = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({"Result":points, "whichOnesRight": whichOnesRight}),
};
let data
fetch('https://api.tor-netzwerk-seminarfach2024.com/apache-test/', myPostRequest).then(
(response) => data = response.json()).then(
(data) => {showResultAnalyse(data)})
}
function showResultAnalyse(data){
console.log(data)
let averageScore = (data["sumScore"] / data["sumRequests"]).toFixed(2)
let myResult = data["myResult"]
changeLinksToStatistics([
data["buttonOne"],data["buttonTwo"],data["buttonThree"],
data["buttonFour"],data["buttonFive"],data["buttonSix"],
data["buttonSeven"],data["buttonEight"],data["buttonNine"]
],
data["sumRequests"]
)
swal(
{
text:`${checkWhichText(myResult,averageScore,data["sumRequests"] )}`,
icon: myResult > averageScore ?"success": "error",
button:"Oki doki",
}
);
}

NOT NULL constraint failed: accounts_personalcolor.user_id

I am new to Django and have trouble making django-rest-framework API for post, inheriting APIView. I'm using a serializer, that inherits djangos ModelSerializer. I face NOT NULL constraint failed: accounts_personalcolor.user_id error whenever I try saving the serializer or model object.
color.js posts image using Django rest framework as follows.
function PersonalColorScreen({navigation,route}) {
const {image} = route.params;
console.log('uri is', image.uri);
const [userToken, setUserToken] = React.useState(route.params?.userToken);
const requestHeaders = {
headers: {
"Content-Type": "multipart/form-data"
}
}
// helper function: generate a new file from base64 String
//convert base64 image data to file object to pass it onto imagefield of serializer.
//otherwise, serializer outputs 500 Internal server error code
const dataURLtoFile = (dataurl, filename) => {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n) {
u8arr[n - 1] = bstr.charCodeAt(n - 1)
n -= 1 // to make eslint happy
}
return new File([u8arr], filename, { type: mime })
}
//random number between 0-9
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
// generate file from base64 string
const file = dataURLtoFile(image.uri, `${getRandomInt(10)}.png`)
const formData= new FormData();
formData.append('img',file,file.name);
console.log(file.name);
//axios post request to send data
// axios.post('http://localhost:8000/accounts/personalcolor/', formData,requestHeaders)
//multipartparser
axios.post('http://localhost:8000/accounts/personalcolor/', formData, requestHeaders)
.then(res => {
console.log(res);
if (res.data === 'upload another image') {
setimageError('upload another image');
} else {
// signUp(userToken);
let color;
switch (res.data){
case ('spring'):
color = 'spring';
break;
case ('summer'):
color = 'summer';
break;
case ('fall'):
color = 'fall';
break;
case ('winter'):
color = 'winter';
break;
}
}
})
.catch(err => {
console.error(err.response.data)
})
view.py handles the image posted. I tried #1 but it did not work. So I tried #2, or #3 instead and they return the same error saying NOT NULL constraint failed: accounts_personalcolor.user_id. I thought saving the serializer or model object creates id(Autofield)automatically and I don't understand why I face this error.
views.py
#api_view(['POST'])
def personalcolor(request):
# 1
image=request.FILES['img']
personal_color=Personalcolor()
personal_color.img=image
personal_color.save()
# 2
image=request.FILES['img']
personal_color=Personalcolor.objects.create(img=image)
personal_color.save()
# 3
serializer = ColorSerializer(data=request.data)
# validation of input data
if serializer.is_valid():
serializer.save()
else:
return Response(serializer.errors, status = status.HTTP_400_BAD_REQUEST)
model.py
class Personalcolor(models.Model):
objects = models.Manager()
img = models.ImageField('personal_img',upload_to="personalcolor/", blank=True)
serializer.py
class ColorSerializer(serializers.ModelSerializer):
class Meta:
model = Personalcolor
fields = ['img']
As mentioned above, executing the code returns django.db.utils.IntegrityError: NOT NULL constraint failed: accounts_personalcolor.user_id. Any help would be greatly appreciated.
Set null to true in your img field like:
img = models.ImageField('personal_img',upload_to="personalcolor/", blank=True, null=True)
Then in your migrations folder within the app where the Personalcolor model is located, delete all of the files that look like 000*_initial.py
Then run makemigrations and migrate

How to get the output of a shell command to a React frontend through a Flask RESTful API?

I am trying to get the output of a shell command to a React frontend through a Flask RESTful API.
class SerVer(Resource):
def put(self):
args = cred_put_args.parse_args()
cred = args
return cred, 201
for it in cred:
client = SSHClient()
client.set_missing_host_key_policy(AutoAddPolicy())
client.load_system_host_keys()
client.connect(it.ip, it.uname, it.pwd)
stdin, stdout, stderr = client.exec_command('ps aux')
psaux = (f'STDOUT: {stdout.read().decode("utf8")}')
def get(self):
return {'data': psaux}, 203
api.add_resource(SerVer, '/request', '/psaux')
The GET request is sent from react, like so:
const [psaux, psauxSet] = useState();
useEffect(() => {
axios.get("http://127.0.0.1:5000/request").then((res) => {
const i = res.data;
console.log(i);
psauxSet(i);
});
}, []);
I understand the problem is variable scoping. I had it working at some point, that I'm trying to reproduce :)
Because the indentation of the code is wrong, it should probably be:
from flask import Response
class SerVer(Resource):
def put(self):
args = cred_put_args.parse_args()
cred = args
return cred, 201
for it in cred:
client = SSHClient()
client.set_missing_host_key_policy(AutoAddPolicy())
client.load_system_host_keys()
client.connect(it.ip, it.uname, it.pwd)
stdin, stdout, stderr = client.exec_command('ps aux')
psaux = (f'STDOUT: {stdout.read().decode("utf8")}')
def get(self):
res = {
'data': 'psaux'
}
return Response(mimetype="application/json", response=json.dumps(res), status=203)
Pay also attention when you add your Resource object (SerVer) to the api object, take a look here

Asp.net core file upload with Graphql-dotnet

I am trying to upload an image file with graphql-dotnet, but it is never successful.
I am taking file object in my GraphQLController:
var files = this.Request.Form.Files;
var executionOptions = new ExecutionOptions
{
Schema = _schema,
Query = queryToExecute,
Inputs = inputs,
UserContext = files,
OperationName = query.OperationName
};
And here my Mutation:
Field<UserGraphType>(
"uploadUserAvatar",
Description="Kullanıcı resmi yükleme.",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<IntGraphType>> { Name = "Id", Description = "Identity Alanı" }
),
resolve: context => {
var file = context.UserContext.As<IFormCollection>();
var model = userService.UploadAvatar(context.GetArgument<int>("Id"),file);
return true;
}
);
I think it is accepting the only JSON. It is not accepting the request as a file type.
Also I am using React & apollo-client at the client-side. It has an error in the console:
Failed to load http://localhost:5000/graphql: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I am trying to send the query like this:
const { selectedFile,id } = this.state
this.props.uploadAvatar({
variables: {id},
file:selectedFile
}).then(result => {
console.log(result);
});
What can I do to achieve this?
Failed to load http://localhost:5000/graphql: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8080' is therefore not allowed
access.
This error means you need to enable CORS.
See these docs: https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1
Essentially you need these two things:
services.AddCors();
app.UseCors(builder =>
builder.WithOrigins("http://example.com"));
I would also suggest to look at this Deserializer helper function in the GraphQL.Relay project. It helps your server handle a multipart/form-data request. You can then use the parsed query information and files and pass it to the DocumentExecutor.
https://github.com/graphql-dotnet/relay/blob/master/src/GraphQL.Relay/Http/Deserializer.cs
public static class Deserializer
{
public static async Task<RelayRequest> Deserialize(Stream body, string contentType)
{
RelayRequest queries;
switch (contentType)
{
case "multipart/form-data":
queries = DeserializeFormData(body);
break;
case "application/json":
var stream = new StreamReader(body);
queries = DeserializeJson(await stream.ReadToEndAsync());
break;
default:
throw new ArgumentOutOfRangeException($"Unknown media type: {contentType}. Cannot deserialize the Http request");
}
return queries;
}
private static RelayRequest DeserializeJson(string stringContent)
{
if (stringContent[0] == '[')
return new RelayRequest(
JsonConvert.DeserializeObject<RelayQuery[]>(stringContent),
isBatched: true
);
if (stringContent[0] == '{')
return new RelayRequest() {
JsonConvert.DeserializeObject<RelayQuery>(stringContent)
};
throw new Exception("Unrecognized request json. GraphQL queries requests should be a single object, or an array of objects");
}
private static RelayRequest DeserializeFormData(Stream body)
{
var form = new MultipartFormDataParser(body);
var req = new RelayRequest()
{
Files = form.Files.Select(f => new HttpFile {
ContentDisposition = f.ContentDisposition,
ContentType = f.ContentType,
Data = f.Data,
FileName = f.FileName,
Name = f.Name
})
};
req.Add(new RelayQuery {
Query = form.Parameters.Find(p => p.Name == "query").Data,
Variables = form.Parameters.Find(p => p.Name == "variables").Data.ToInputs(),
});
return req;
}
}

Resources