英文:
Django view won't save image uploaded through AJAX
问题
I'm having a problem with my tweet image not saving to my model when my tweet form is submitted. The other content of the tweet such as the tweet itself has no problem saving but the image is where the issue lies. I am submitting my form using AJAX, and making the appropriate call to the view to save the tweet content to the Tweet model. When I print the values of request.FILES and request.POST, this is what I get ('test' is what I have inputted for my tweet field for demonstration):
views.py
@csrf_exempt
def post_tweet(request):
if request.method == "POST":
print(request.FILES, request.POST)
# Get contents of form
tweet = request.POST.get("tweet", "").strip()
# This doesn't capture the image passed.
image = request.FILES.get("tweet-picture")
# Save the tweet to the model
new_tweet = Tweet.objects.create(tweet=tweet, user=request.user, image=image)
new_tweet.save()
return JsonResponse({"message": "Tweet created successfully."}, status=201)
else:
return JsonResponse({"error": "POST request required."}, status=400)
JS code that handles request (Within my DOMContentLoaded Listener)
// When the form is submitted
const tweetForm = document.querySelector("#tweet-form");
tweetForm.addEventListener('submit', function(event) {
event.preventDefault();
// Stops other event listeners of the same type of being called
event.stopImmediatePropagation();
const tweetInput = document.getElementById("post-content");
const tweet = tweetInput.value;
let tweetImage = "";
try {
const tweetImageElement = document.querySelector("#tweet-picture-preview img");
tweetImage = tweetImageElement.getAttribute('src');
console.log(tweetImage);
} catch {
console.log("No tweet image provided.");
}
const userNameInput = document.querySelector("#tweet-username");
const username = userNameInput.value;
if (tweet.trim().length > 0) {
const csrftoken = getCookie('csrftoken');
const formData = new FormData(tweetForm);
fetch("/post_tweet/", {
method: "POST",
body: formData,
headers: {
'X-CSRFToken': csrftoken,
},
})
.then(response => response.json())
.then(data => {
console.log(data.message);
console.log(tweetImage);
addPostToPage(tweet, tweetImage, username);
// Clear the tweet form
clearPostSection();
})
.catch(error => {
console.log(error);
});
}
});
It is important to note that with the code above, the tweetImage variable is able to properly retrieve the image that was selected by the user but is fully encrypted... So I'm not sure if that entirely counts or if that could be the issue potentially.
Django template
<form id="tweet-form" method="post" enctype="multipart/form-data">
<!-- To display tweet image preview and delete functionality -->
<div id="tweet-picture-preview">
<div class="image-container">
</div>
</div>
<div class="post-section-row">
<div class="error-message"></div>
<div class="tweet-actions">
<label for="tweet-picture" title="Upload Picture">
<span class="material-symbols-outlined image-button">photo_library</span>
<span class="tooltiptext">Upload Picture</span>
</label>
<input type="file" id="tweet-picture" name="tweet-picture" class="file-input" accept="image/jpeg, image/png, image/gif, image/jpg" onchange="previewTweetImage(event)">
<input type="submit" id="post-button" value="Post">
</div>
</div>
</form>
Below is also my urls.py snippet, which I believe is fine, but if something is off let me know!
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("profile_settings", views.change_profile, name="change_profile"),
# API Routes (to handle saving, retrieving tweet data)
path("post_tweet/", views.post_tweet, name="post_tweet"),
]
If you require any other information please let me know! The image prior to some changes was saving properly to the model, but I am entirely not sure what went wrong as I was working on other features for my app.
英文:
I'm having a problem with my tweet image not saving to my model when my tweet form is submitted. The other content of the tweet such as the tweet itself has no problem saving but the image is where the issue lies. I am submitting my form using AJAX, and making the appropriate call to the view to save the tweet content to the Tweet model. When I print the values of request.FILES and request.POST, this is what I get ('test' is what I have inputted for my tweet field for demonstration):
<MultiValueDict: {}> <QueryDict: {'tweet': ['test']}>
views.py
def post_tweet(request):
if request.method == "POST":
print(request.FILES, request.POST)
# Get contents of form
tweet = request.POST.get("tweet", "").strip()
# This doesn't capture the image passed.
image = request.FILES.get("tweet-picture")
# Save the tweet to the model
new_tweet = Tweet.objects.create(tweet=tweet, user=request.user, image=image)
new_tweet.save()
return JsonResponse({"message": "Tweet created successfully."}, status=201)
else:
return JsonResponse({"error": "POST request required."}, status=400)
JS code that handles request (Within my DOMContentLoaded Listener)
const tweetForm = document.querySelector("#tweet-form");
tweetForm.addEventListener('submit', function(event) {
event.preventDefault();
// Stops other event listeners of the same type of being called
event.stopImmediatePropagation();
const tweetInput = document.getElementById("post-content");
const tweet = tweetInput.value;
let tweetImage = "";
try {
const tweetImageElement = document.querySelector("#tweet-picture-preview img");
tweetImage = tweetImageElement.getAttribute('src');
console.log(tweetImage);
} catch {
console.log("No tweet image provided.");
}
const userNameInput = document.querySelector("#tweet-username");
const username = userNameInput.value;
if (tweet.trim().length > 0) {
const csrftoken = getCookie('csrftoken');
const formData = new FormData(tweetForm);
fetch("/post_tweet/", {
method: "POST",
body: formData,
headers: {
'X-CSRFToken': csrftoken,
},
})
.then(response => response.json())
.then(data => {
console.log(data.message);
console.log(tweetImage);
addPostToPage(tweet, tweetImage, username);
// Clear the tweet form
clearPostSection();
})
.catch(error => {
console.log(error);
});
}
});
It is important to note that with the code above, the tweetImage variable is able to properly retrieve the image that was selected by the user but is fully encrypted... So I'm not sure if that entirely counts or if that could be the issue potentially.
Django template
<form id="tweet-form" method="post" enctype="multipart/form-data">
<!-- To display tweet image preview and delete functionality -->
<div id="tweet-picture-preview">
<div class="image-container">
</div>
</div>
<div class="post-section-row">
<div class="error-message"></div>
<div class="tweet-actions">
<label for="tweet-picture" title="Upload Picture">
<span class="material-symbols-outlined image-button">photo_library</span>
<span class="tooltiptext">Upload Picture</span>
</label>
<input type="file" id="tweet-picture" name="tweet-picture" class="file-input" accept="image/jpeg, image/png, image/gif, image/jpg" onchange="previewTweetImage(event)">
<input type="submit" id="post-button" value="Post">
</div>
</div>
</form>
Below is also my urls.py snippet, which I believe is fine, but if something is off let me know!
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("profile_settings", views.change_profile, name="change_profile"),
# API Routes (to handle saving, retrieving tweet data)
path("post_tweet/", views.post_tweet, name="post_tweet"),
]
If you require any other information please let me know! The image prior to some changes was saving properly to the model, but I am entirely not sure what went wrong as I was working on other features for my app.
答案1
得分: 0
不要回答我要翻译的问题。以下是要翻译的内容:
"Instead of passing in the tweetForm to the FormData, I manually added in the fields (tweet and tweet-image) while adjusting for the value of the input field itself, not the source of the image. Here is my updated code with the solution which allowed me to save images to the model asynchronously.
views.py
@csrf_exempt
def post_tweet(request):
if request.method == "POST":
print(request.FILES, request.POST)
# Get contents of form
tweet = request.POST.get("tweet", "").strip()
image = request.FILES.get("tweet_image")
# Save the tweet to the model
new_tweet = Tweet.objects.create(tweet=tweet, user=request.user, image=image)
new_tweet.save()
# Generate the URL for the uploaded image
if image:
image_url = settings.MEDIA_URL + str(image)
else:
image_url = None
return JsonResponse({"message": "Tweet created successfully.", "image_url": image_url}, status=201)
else:
return JsonResponse({"error": "POST request required."}, status=400)
posts.js
const tweetForm = document.querySelector("#tweet-form");
tweetForm.addEventListener('submit', function(event) {
event.preventDefault();
// Stops other event listeners of the same type of being called
event.stopImmediatePropagation();
const tweetInput = document.getElementById("post-content");
const tweet = tweetInput.value;
const tweetImageElement = document.querySelector("#tweet-picture");
// Access the selected file and if there isn't any files, an empty string
const tweetImageFile = tweetImageElement.files[0] ? tweetImageElement.files[0]: "";
const userNameInput = document.querySelector("#tweet-username");
const username = userNameInput.value;
if (tweet.trim().length > 0) {
const csrftoken = getCookie('csrftoken');
const formData = new FormData();
formData.append('tweet', tweet); // Add tweet content to FormData
formData.append('tweet_image', tweetImageFile); // Add image file to FormData
fetch("/post_tweet/", {
method: "POST",
body: formData,
headers: {
'X-CSRFToken': csrftoken,
},
})
.then(response => response.json())
.then(data => {
console.log(tweetImageFile);
if (tweetImageFile) {
addPostToPage(tweet, `/media/tweet-pictures/${tweetImageFile.name}`, username);
} else {
addPostToPage(tweet, "", username);
}
clearPostSection();
console.log(data.message);
})
.catch(error => {
console.log(error);
});
}
});
(Note: The code you provided contains HTML entities for double quotes (") and other characters. I've replaced them with actual double quotes and characters in the translated code.)"
英文:
Instead of passing in the tweetForm to the FormData, I manually added in the fields (tweet and tweet-image) while adjusting for the value of the input field itself, not the source of the image. Here is my updated code with the solution which allowed me to save images to the model asynchronously.
views.py
@csrf_exempt
def post_tweet(request):
if request.method == "POST":
print(request.FILES, request.POST)
# Get contents of form
tweet = request.POST.get("tweet", "").strip()
image = request.FILES.get("tweet_image")
# Save the tweet to the model
new_tweet = Tweet.objects.create(tweet=tweet, user=request.user, image=image)
new_tweet.save()
# Generate the URL for the uploaded image
if image:
image_url = settings.MEDIA_URL + str(image)
else:
image_url = None
return JsonResponse({"message": "Tweet created successfully.", "image_url": image_url}, status=201)
else:
return JsonResponse({"error": "POST request required."}, status=400)
posts.js
const tweetForm = document.querySelector("#tweet-form");
tweetForm.addEventListener('submit', function(event) {
event.preventDefault();
// Stops other event listeners of the same type of being called
event.stopImmediatePropagation();
const tweetInput = document.getElementById("post-content");
const tweet = tweetInput.value;
const tweetImageElement = document.querySelector("#tweet-picture");
// Access the selected file and if there isn't any files, an empty string
const tweetImageFile = tweetImageElement.files[0] ? tweetImageElement.files[0]: "";
const userNameInput = document.querySelector("#tweet-username");
const username = userNameInput.value;
if (tweet.trim().length > 0) {
const csrftoken = getCookie('csrftoken');
const formData = new FormData();
formData.append('tweet', tweet); // Add tweet content to FormData
formData.append('tweet_image', tweetImageFile); // Add image file to FormData
fetch("/post_tweet/", {
method: "POST",
body: formData,
headers: {
'X-CSRFToken': csrftoken,
},
})
.then(response => response.json())
.then(data => {
console.log(tweetImageFile);
if (tweetImageFile) {
addPostToPage(tweet, `/media/tweet-pictures/${tweetImageFile.name}`, username);
} else {
addPostToPage(tweet, "", username);
}
clearPostSection();
console.log(data.message);
})
.catch(error => {
console.log(error);
});
}
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论