django 没有读取 javascript 表单数据文件
django is not reading javascript form-data files
所以当我尝试将文件发送到 Django 服务器时,它引发了大量错误:
Traceback (most recent call last):
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py", line 2972, in open
fp.seek(0)
AttributeError: 'NoneType' object has no attribute 'seek'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 482, in thread_handler
raise exc_info[1]
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 38, in inner
response = await get_response(request)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 233, in _get_response_async
response = await wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 444, in __call__
ret = await asyncio.wait_for(future, timeout=None)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\asyncio\tasks.py", line 442, in wait_for
return await fut
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\concurrent\futures\thread.py", line 52, in run
result = self.fn(*self.args, **self.kwargs)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 486, in thread_handler
return func(*args, **kwargs)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\TM\سطح المكتب\New folder\web\views.py", line 86, in makeAccountApi
IMG=RESIZE(Image)
File "C:\Users\TM\سطح المكتب\New folder\web\helpers.py", line 110, in RESIZE
im = Image.open(Img)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py", line 2974, in open
fp = io.BytesIO(fp.read())
AttributeError: 'NoneType' object has no attribute 'read'
当我 print request.body 并请求文件并请求 POST 它打印:
b'[object FormData]'
<MultiValueDict: {}>
<QueryDict: {}>
当我打印文件时 console.log:
C:\fakepath\download.jpg
然后是 console.log:
request.js:62 [Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
PostData @ request.js:62
sumbit @ login.js:8
(anonymous) @ VM103:1
request.js:64 POST http://127.0.0.1:8000/api/makeuser/dsa/ 400 (Bad Request)
而且我也没有制作按钮来触发该功能,所以我从控制台触发该功能
在此处输入图片描述
enter image description here
------------代码部分:
对于请求函数:
function PostData(url, method="get", data="") {
url=url.toString();
method=method.toString();
data=data.toString();
//CHECK CSRF-Token
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var 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;
}
//Check if there is a hidden csrf-input-field, if so, get the value
try {
var csrffield = document.getElementsByTagName("input");
var l = csrffield.length;
var i=0;
while (true) {
if (i > l) {
break;
}
if (csrffield[i].name.toLowerCase().includes("csrf") == true) {
csrftoken=csrffield[i].value;
break;
}
i++;
}}
catch (err) {
var csrftoken = getCookie('csrftoken');
}
var req = new XMLHttpRequest();
if (method == "get" || method == "GET" || method == "Get") {
req.open("GET", url, false);
req.send();
if (req.status == 200) {
return req.responseText;
}}
if (method == "post" || method == "POST" || method == "Post") {
req.open("POST", url, false);
req.setRequestHeader('Content-Type','multipart/form-data')
req.send(data);
return req.responseText;
}}
求和函数:
function sumbit() {
var errorhandler = document.getElementById("Error")
var user = document.getElementById("user").value;
var file = document.getElementById("pfp").value;
console.log(file,user)
var formData = new FormData();
formData.append("Image",file);
request = PostData(`http://127.0.0.1:8000/api/makeuser/${user}/`,'POST',formData)
if(request == "555") {
errorhandler.innerHTML = "Image or User required to make account";
}
else if(request=="556") {
errorhandler.innerHTML = "User already in use";
}
else if(request=="Made") {
window.location= "http://127.0.0.1:8000/joinroom/"
}else {
errorhandler.innerHTML = "Unkown error";
}
}
这里是完整版的 views.py:
from django.http.response import HttpResponse
from django.shortcuts import render
from .models import rooms,accounts
from .helpers import RESIZE,file_size,BasicToken #Importing helpers functions
from django.utils.crypto import get_random_string
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
def login(request):
return render(request,'loginpage.html')
def makeroom(request):
return render(request,'makeroom.html')
def joinroom(request):
return render(request,'joinroom.html')
def chatroom(request,ID):
return render(request,'chatroom.html')
#Api
#this Api makes chatting rooms
def makeroomApi(request):
Name = 'dd'
namegenerated=False
#Here the ID generated
while(namegenerated==False) :
Name = get_random_string(length=6)
try :
rooms.objects.get(roomid=Name)
namegenerated=False
except:
namegenerated=True
pass
room = rooms(roomid=Name)
room.save()
return HttpResponse(Name)
#this Api makes chatting rooms
@csrf_exempt
def makeAccountApi(request,User):
print(request.body)
print(request.FILES)
## 555 error means that theres data we need that is not in our request
## 12 means that method is not post
## 556 mean that user is already available
## 212 means that file's size is big
try:
if User.isspace():
print(User.isspace())
print("555")
return HttpResponse("555")
except:
print("555")
return HttpResponse("555")
if request.method == 'POST':
Image=request.FILES.get("Image")
print(request.body)
IMG=RESIZE(Image)
token=BasicToken()
if file_size(Image,2) == 1:
print('33')
return HttpResponse("212")
#Handling if the same user is used by some one
try:
accounts.objects.get(user=User)
print("user in use")
return HttpResponse('556')
except:
#if the user is not available then save to database
room = accounts(user=User,image=IMG,token=token)
room.save()
print("made")
return HttpResponse('Made')
else:
return HttpResponse("12")
这里是views.py的简化版本:
请求函数
@csrf_exempt
def makeuser(request,User):
if request.method == 'POST':
Image=request.FILES.get("Image")
print(request.body)
IMG=RESIZE(Image)
token=BasicToken()
if file_size(Image,2) == 1:
print('33')
return HttpResponse("212")
#Handling if the same user is used by some one
try:
accounts.objects.get(user=User)
print("user in use")
return HttpResponse('556')
except:
#if the user is not available then save to database
room = accounts(user=User,image=IMG,token=token)
room.save()
print("made")
return HttpResponse('Made')
图像处理函数:
def RESIZE(Img):
mask = Image.open(Mask).convert('L')
im = Image.open(Img)
outputimage = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
outputimage.putalpha(mask)
#Convering the image to django file so we can upload it to our database
image_io = io.BytesIO()
outputimage.save(image_io, format='png')
outputimage = '{}.{}'.format('filename','.png')
image = ContentFile(image_io.getvalue(), outputimage)
return image
我的完整 HTML 代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/x-icon" href="http://127.0.0.1:8000/files/Logo.ico" />
<meta name="keywords" content="chat,chatting,roomchat,groupchat,group">
<meta name="description" content="Free chatting website!
you can chat now with ur friends with our rooms chat service">
<meta property="og:image" content="https://developer.mozilla.org/static/img/opengraph-logo.png">
<meta property="og:description" content="Free chatting website!
you can chat now with ur friends with our rooms chat service">
<meta property="og:title" content="Chatting">
<style>
@import url('https://fonts.googleapis.com/css2?family=Almarai:wght@300&display=swap');
div {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
min-height: 100vh;
}
h1 {
font-family: "Almarai";
}
.inputimage {
margin: 5px;
font-size: larger;
padding-left: 10%;
}
.inputuser{
border: 0px;
padding: 3px;
border-bottom: 5px solid RGB(0,0,0,33%);
font-size: 20px;
font-family: "Almarai";
}
.inputuser:focus {
font-size: 22px;
outline: none;
}
.sumbitbutton {
margin:10px;
color:black;
background-color: transparent;
border-color: black;
border-style: solid;
border-width: 2px;
width: 17vh;
min-width: 179px;
font-size: 32px;
border-radius: 20px;
cursor: pointer;
}
.sumbitbutton:hover {
background-color:black;
color:white;
}
</style>
<title>Login page</title>
</head>
<body>
<div>
<form action = "http://127.0.0.1:8000/api/makeuser/taha/" method = "POST">
<h1 id="Error"></h1>
<input type='text' id="user" autofocus placeholder="Username" class="inputuser">
<h1>Your PFP</h1>
<input type="file" id="pfp" alt="" class="inputimage" accept=".jpg,.png">
<input type="submit">
</form>
</div>
<script type="text/javascript" src="http://127.0.0.1:8000/files/request.js"></script>
<script type="text/javascript" src="http://127.0.0.1:8000/files/login.js"></script>
</body>
</html>
不要将您的数据转换为字符串
url=url.toString(); // url is already a string, don't do this
method=method.toString(); // method is already a string, don't do this
data=data.toString(); // don't convert data to a string, if it needed to be a string it should have been passed as a string(It doesn't). Don't do this
另外,不要为multipart/form-data设置content-type header,它会自动正确设置。
您正在使用同步 ajax,这就是您收到弃用警告的原因。这将导致糟糕的用户体验,尤其是在文件上传时。
如果你想保持代码的流动,你可以看看 async/await、Promises 和 Fetch API。
所以当我尝试将文件发送到 Django 服务器时,它引发了大量错误:
Traceback (most recent call last):
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py", line 2972, in open
fp.seek(0)
AttributeError: 'NoneType' object has no attribute 'seek'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 482, in thread_handler
raise exc_info[1]
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 38, in inner
response = await get_response(request)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 233, in _get_response_async
response = await wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 444, in __call__
ret = await asyncio.wait_for(future, timeout=None)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\asyncio\tasks.py", line 442, in wait_for
return await fut
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\concurrent\futures\thread.py", line 52, in run
result = self.fn(*self.args, **self.kwargs)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 486, in thread_handler
return func(*args, **kwargs)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\TM\سطح المكتب\New folder\web\views.py", line 86, in makeAccountApi
IMG=RESIZE(Image)
File "C:\Users\TM\سطح المكتب\New folder\web\helpers.py", line 110, in RESIZE
im = Image.open(Img)
File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py", line 2974, in open
fp = io.BytesIO(fp.read())
AttributeError: 'NoneType' object has no attribute 'read'
当我 print request.body 并请求文件并请求 POST 它打印:
b'[object FormData]'
<MultiValueDict: {}>
<QueryDict: {}>
当我打印文件时 console.log:
C:\fakepath\download.jpg
然后是 console.log:
request.js:62 [Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
PostData @ request.js:62
sumbit @ login.js:8
(anonymous) @ VM103:1
request.js:64 POST http://127.0.0.1:8000/api/makeuser/dsa/ 400 (Bad Request)
而且我也没有制作按钮来触发该功能,所以我从控制台触发该功能 在此处输入图片描述
enter image description here
------------代码部分: 对于请求函数:
function PostData(url, method="get", data="") {
url=url.toString();
method=method.toString();
data=data.toString();
//CHECK CSRF-Token
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var 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;
}
//Check if there is a hidden csrf-input-field, if so, get the value
try {
var csrffield = document.getElementsByTagName("input");
var l = csrffield.length;
var i=0;
while (true) {
if (i > l) {
break;
}
if (csrffield[i].name.toLowerCase().includes("csrf") == true) {
csrftoken=csrffield[i].value;
break;
}
i++;
}}
catch (err) {
var csrftoken = getCookie('csrftoken');
}
var req = new XMLHttpRequest();
if (method == "get" || method == "GET" || method == "Get") {
req.open("GET", url, false);
req.send();
if (req.status == 200) {
return req.responseText;
}}
if (method == "post" || method == "POST" || method == "Post") {
req.open("POST", url, false);
req.setRequestHeader('Content-Type','multipart/form-data')
req.send(data);
return req.responseText;
}}
求和函数:
function sumbit() {
var errorhandler = document.getElementById("Error")
var user = document.getElementById("user").value;
var file = document.getElementById("pfp").value;
console.log(file,user)
var formData = new FormData();
formData.append("Image",file);
request = PostData(`http://127.0.0.1:8000/api/makeuser/${user}/`,'POST',formData)
if(request == "555") {
errorhandler.innerHTML = "Image or User required to make account";
}
else if(request=="556") {
errorhandler.innerHTML = "User already in use";
}
else if(request=="Made") {
window.location= "http://127.0.0.1:8000/joinroom/"
}else {
errorhandler.innerHTML = "Unkown error";
}
}
这里是完整版的 views.py:
from django.http.response import HttpResponse
from django.shortcuts import render
from .models import rooms,accounts
from .helpers import RESIZE,file_size,BasicToken #Importing helpers functions
from django.utils.crypto import get_random_string
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
def login(request):
return render(request,'loginpage.html')
def makeroom(request):
return render(request,'makeroom.html')
def joinroom(request):
return render(request,'joinroom.html')
def chatroom(request,ID):
return render(request,'chatroom.html')
#Api
#this Api makes chatting rooms
def makeroomApi(request):
Name = 'dd'
namegenerated=False
#Here the ID generated
while(namegenerated==False) :
Name = get_random_string(length=6)
try :
rooms.objects.get(roomid=Name)
namegenerated=False
except:
namegenerated=True
pass
room = rooms(roomid=Name)
room.save()
return HttpResponse(Name)
#this Api makes chatting rooms
@csrf_exempt
def makeAccountApi(request,User):
print(request.body)
print(request.FILES)
## 555 error means that theres data we need that is not in our request
## 12 means that method is not post
## 556 mean that user is already available
## 212 means that file's size is big
try:
if User.isspace():
print(User.isspace())
print("555")
return HttpResponse("555")
except:
print("555")
return HttpResponse("555")
if request.method == 'POST':
Image=request.FILES.get("Image")
print(request.body)
IMG=RESIZE(Image)
token=BasicToken()
if file_size(Image,2) == 1:
print('33')
return HttpResponse("212")
#Handling if the same user is used by some one
try:
accounts.objects.get(user=User)
print("user in use")
return HttpResponse('556')
except:
#if the user is not available then save to database
room = accounts(user=User,image=IMG,token=token)
room.save()
print("made")
return HttpResponse('Made')
else:
return HttpResponse("12")
这里是views.py的简化版本:
请求函数
@csrf_exempt
def makeuser(request,User):
if request.method == 'POST':
Image=request.FILES.get("Image")
print(request.body)
IMG=RESIZE(Image)
token=BasicToken()
if file_size(Image,2) == 1:
print('33')
return HttpResponse("212")
#Handling if the same user is used by some one
try:
accounts.objects.get(user=User)
print("user in use")
return HttpResponse('556')
except:
#if the user is not available then save to database
room = accounts(user=User,image=IMG,token=token)
room.save()
print("made")
return HttpResponse('Made')
图像处理函数:
def RESIZE(Img):
mask = Image.open(Mask).convert('L')
im = Image.open(Img)
outputimage = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
outputimage.putalpha(mask)
#Convering the image to django file so we can upload it to our database
image_io = io.BytesIO()
outputimage.save(image_io, format='png')
outputimage = '{}.{}'.format('filename','.png')
image = ContentFile(image_io.getvalue(), outputimage)
return image
我的完整 HTML 代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/x-icon" href="http://127.0.0.1:8000/files/Logo.ico" />
<meta name="keywords" content="chat,chatting,roomchat,groupchat,group">
<meta name="description" content="Free chatting website!
you can chat now with ur friends with our rooms chat service">
<meta property="og:image" content="https://developer.mozilla.org/static/img/opengraph-logo.png">
<meta property="og:description" content="Free chatting website!
you can chat now with ur friends with our rooms chat service">
<meta property="og:title" content="Chatting">
<style>
@import url('https://fonts.googleapis.com/css2?family=Almarai:wght@300&display=swap');
div {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
min-height: 100vh;
}
h1 {
font-family: "Almarai";
}
.inputimage {
margin: 5px;
font-size: larger;
padding-left: 10%;
}
.inputuser{
border: 0px;
padding: 3px;
border-bottom: 5px solid RGB(0,0,0,33%);
font-size: 20px;
font-family: "Almarai";
}
.inputuser:focus {
font-size: 22px;
outline: none;
}
.sumbitbutton {
margin:10px;
color:black;
background-color: transparent;
border-color: black;
border-style: solid;
border-width: 2px;
width: 17vh;
min-width: 179px;
font-size: 32px;
border-radius: 20px;
cursor: pointer;
}
.sumbitbutton:hover {
background-color:black;
color:white;
}
</style>
<title>Login page</title>
</head>
<body>
<div>
<form action = "http://127.0.0.1:8000/api/makeuser/taha/" method = "POST">
<h1 id="Error"></h1>
<input type='text' id="user" autofocus placeholder="Username" class="inputuser">
<h1>Your PFP</h1>
<input type="file" id="pfp" alt="" class="inputimage" accept=".jpg,.png">
<input type="submit">
</form>
</div>
<script type="text/javascript" src="http://127.0.0.1:8000/files/request.js"></script>
<script type="text/javascript" src="http://127.0.0.1:8000/files/login.js"></script>
</body>
</html>
不要将您的数据转换为字符串
url=url.toString(); // url is already a string, don't do this
method=method.toString(); // method is already a string, don't do this
data=data.toString(); // don't convert data to a string, if it needed to be a string it should have been passed as a string(It doesn't). Don't do this
另外,不要为multipart/form-data设置content-type header,它会自动正确设置。
您正在使用同步 ajax,这就是您收到弃用警告的原因。这将导致糟糕的用户体验,尤其是在文件上传时。
如果你想保持代码的流动,你可以看看 async/await、Promises 和 Fetch API。