Django视图不会通过AJAX保存上传的图像。

huangapple go评论83阅读模式
英文:

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

  1. @csrf_exempt
  2. def post_tweet(request):
  3. if request.method == "POST":
  4. print(request.FILES, request.POST)
  5. # Get contents of form
  6. tweet = request.POST.get("tweet", "").strip()
  7. # This doesn't capture the image passed.
  8. image = request.FILES.get("tweet-picture")
  9. # Save the tweet to the model
  10. new_tweet = Tweet.objects.create(tweet=tweet, user=request.user, image=image)
  11. new_tweet.save()
  12. return JsonResponse({"message": "Tweet created successfully."}, status=201)
  13. else:
  14. return JsonResponse({"error": "POST request required."}, status=400)

JS code that handles request (Within my DOMContentLoaded Listener)

  1. // When the form is submitted
  2. const tweetForm = document.querySelector("#tweet-form");
  3. tweetForm.addEventListener('submit', function(event) {
  4. event.preventDefault();
  5. // Stops other event listeners of the same type of being called
  6. event.stopImmediatePropagation();
  7. const tweetInput = document.getElementById("post-content");
  8. const tweet = tweetInput.value;
  9. let tweetImage = "";
  10. try {
  11. const tweetImageElement = document.querySelector("#tweet-picture-preview img");
  12. tweetImage = tweetImageElement.getAttribute('src');
  13. console.log(tweetImage);
  14. } catch {
  15. console.log("No tweet image provided.");
  16. }
  17. const userNameInput = document.querySelector("#tweet-username");
  18. const username = userNameInput.value;
  19. if (tweet.trim().length > 0) {
  20. const csrftoken = getCookie('csrftoken');
  21. const formData = new FormData(tweetForm);
  22. fetch("/post_tweet/", {
  23. method: "POST",
  24. body: formData,
  25. headers: {
  26. 'X-CSRFToken': csrftoken,
  27. },
  28. })
  29. .then(response => response.json())
  30. .then(data => {
  31. console.log(data.message);
  32. console.log(tweetImage);
  33. addPostToPage(tweet, tweetImage, username);
  34. // Clear the tweet form
  35. clearPostSection();
  36. })
  37. .catch(error => {
  38. console.log(error);
  39. });
  40. }
  41. });

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

  1. <form id="tweet-form" method="post" enctype="multipart/form-data">
  2. <!-- To display tweet image preview and delete functionality -->
  3. <div id="tweet-picture-preview">
  4. <div class="image-container">
  5. </div>
  6. </div>
  7. <div class="post-section-row">
  8. <div class="error-message"></div>
  9. <div class="tweet-actions">
  10. <label for="tweet-picture" title="Upload Picture">
  11. <span class="material-symbols-outlined image-button">photo_library</span>
  12. <span class="tooltiptext">Upload Picture</span>
  13. </label>
  14. <input type="file" id="tweet-picture" name="tweet-picture" class="file-input" accept="image/jpeg, image/png, image/gif, image/jpg" onchange="previewTweetImage(event)">
  15. <input type="submit" id="post-button" value="Post">
  16. </div>
  17. </div>
  18. </form>

Below is also my urls.py snippet, which I believe is fine, but if something is off let me know!

urls.py

  1. from django.urls import path
  2. from . import views
  3. urlpatterns = [
  4. path("", views.index, name="index"),
  5. path("login", views.login_view, name="login"),
  6. path("logout", views.logout_view, name="logout"),
  7. path("register", views.register, name="register"),
  8. path("profile_settings", views.change_profile, name="change_profile"),
  9. # API Routes (to handle saving, retrieving tweet data)
  10. path("post_tweet/", views.post_tweet, name="post_tweet"),
  11. ]

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):

&lt;MultiValueDict: {}&gt; &lt;QueryDict: {&#39;tweet&#39;: [&#39;test&#39;]}&gt;

views.py

  1. def post_tweet(request):
  2. if request.method == &quot;POST&quot;:
  3. print(request.FILES, request.POST)
  4. # Get contents of form
  5. tweet = request.POST.get(&quot;tweet&quot;, &quot;&quot;).strip()
  6. # This doesn&#39;t capture the image passed.
  7. image = request.FILES.get(&quot;tweet-picture&quot;)
  8. # Save the tweet to the model
  9. new_tweet = Tweet.objects.create(tweet=tweet, user=request.user, image=image)
  10. new_tweet.save()
  11. return JsonResponse({&quot;message&quot;: &quot;Tweet created successfully.&quot;}, status=201)
  12. else:
  13. return JsonResponse({&quot;error&quot;: &quot;POST request required.&quot;}, status=400)

JS code that handles request (Within my DOMContentLoaded Listener)

  1. const tweetForm = document.querySelector(&quot;#tweet-form&quot;);
  2. tweetForm.addEventListener(&#39;submit&#39;, function(event) {
  3. event.preventDefault();
  4. // Stops other event listeners of the same type of being called
  5. event.stopImmediatePropagation();
  6. const tweetInput = document.getElementById(&quot;post-content&quot;);
  7. const tweet = tweetInput.value;
  8. let tweetImage = &quot;&quot;;
  9. try {
  10. const tweetImageElement = document.querySelector(&quot;#tweet-picture-preview img&quot;);
  11. tweetImage = tweetImageElement.getAttribute(&#39;src&#39;);
  12. console.log(tweetImage);
  13. } catch {
  14. console.log(&quot;No tweet image provided.&quot;);
  15. }
  16. const userNameInput = document.querySelector(&quot;#tweet-username&quot;);
  17. const username = userNameInput.value;
  18. if (tweet.trim().length &gt; 0) {
  19. const csrftoken = getCookie(&#39;csrftoken&#39;);
  20. const formData = new FormData(tweetForm);
  21. fetch(&quot;/post_tweet/&quot;, {
  22. method: &quot;POST&quot;,
  23. body: formData,
  24. headers: {
  25. &#39;X-CSRFToken&#39;: csrftoken,
  26. },
  27. })
  28. .then(response =&gt; response.json())
  29. .then(data =&gt; {
  30. console.log(data.message);
  31. console.log(tweetImage);
  32. addPostToPage(tweet, tweetImage, username);
  33. // Clear the tweet form
  34. clearPostSection();
  35. })
  36. .catch(error =&gt; {
  37. console.log(error);
  38. });
  39. }
  40. });

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

  1. &lt;form id=&quot;tweet-form&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
  2. &lt;!-- To display tweet image preview and delete functionality --&gt;
  3. &lt;div id=&quot;tweet-picture-preview&quot;&gt;
  4. &lt;div class=&quot;image-container&quot;&gt;
  5. &lt;/div&gt;
  6. &lt;/div&gt;
  7. &lt;div class=&quot;post-section-row&quot;&gt;
  8. &lt;div class=&quot;error-message&quot;&gt;&lt;/div&gt;
  9. &lt;div class=&quot;tweet-actions&quot;&gt;
  10. &lt;label for=&quot;tweet-picture&quot; title=&quot;Upload Picture&quot;&gt;
  11. &lt;span class=&quot;material-symbols-outlined image-button&quot;&gt;photo_library&lt;/span&gt;
  12. &lt;span class=&quot;tooltiptext&quot;&gt;Upload Picture&lt;/span&gt;
  13. &lt;/label&gt;
  14. &lt;input type=&quot;file&quot; id=&quot;tweet-picture&quot; name=&quot;tweet-picture&quot; class=&quot;file-input&quot; accept=&quot;image/jpeg, image/png, image/gif, image/jpg&quot; onchange=&quot;previewTweetImage(event)&quot;&gt;
  15. &lt;input type=&quot;submit&quot; id=&quot;post-button&quot; value=&quot;Post&quot;&gt;
  16. &lt;/div&gt;
  17. &lt;/div&gt;
  18. &lt;/form&gt;

Below is also my urls.py snippet, which I believe is fine, but if something is off let me know!

urls.py

  1. from django.urls import path
  2. from . import views
  3. urlpatterns = [
  4. path(&quot;&quot;, views.index, name=&quot;index&quot;),
  5. path(&quot;login&quot;, views.login_view, name=&quot;login&quot;),
  6. path(&quot;logout&quot;, views.logout_view, name=&quot;logout&quot;),
  7. path(&quot;register&quot;, views.register, name=&quot;register&quot;),
  8. path(&quot;profile_settings&quot;, views.change_profile, name=&quot;change_profile&quot;),
  9. # API Routes (to handle saving, retrieving tweet data)
  10. path(&quot;post_tweet/&quot;, views.post_tweet, name=&quot;post_tweet&quot;),
  11. ]

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

  1. @csrf_exempt
  2. def post_tweet(request):
  3. if request.method == "POST":
  4. print(request.FILES, request.POST)
  5. # Get contents of form
  6. tweet = request.POST.get("tweet", "").strip()
  7. image = request.FILES.get("tweet_image")
  8. # Save the tweet to the model
  9. new_tweet = Tweet.objects.create(tweet=tweet, user=request.user, image=image)
  10. new_tweet.save()
  11. # Generate the URL for the uploaded image
  12. if image:
  13. image_url = settings.MEDIA_URL + str(image)
  14. else:
  15. image_url = None
  16. return JsonResponse({"message": "Tweet created successfully.", "image_url": image_url}, status=201)
  17. else:
  18. return JsonResponse({"error": "POST request required."}, status=400)

posts.js

  1. const tweetForm = document.querySelector("#tweet-form");
  2. tweetForm.addEventListener('submit', function(event) {
  3. event.preventDefault();
  4. // Stops other event listeners of the same type of being called
  5. event.stopImmediatePropagation();
  6. const tweetInput = document.getElementById("post-content");
  7. const tweet = tweetInput.value;
  8. const tweetImageElement = document.querySelector("#tweet-picture");
  9. // Access the selected file and if there isn't any files, an empty string
  10. const tweetImageFile = tweetImageElement.files[0] ? tweetImageElement.files[0]: "";
  11. const userNameInput = document.querySelector("#tweet-username");
  12. const username = userNameInput.value;
  13. if (tweet.trim().length > 0) {
  14. const csrftoken = getCookie('csrftoken');
  15. const formData = new FormData();
  16. formData.append('tweet', tweet); // Add tweet content to FormData
  17. formData.append('tweet_image', tweetImageFile); // Add image file to FormData
  18. fetch("/post_tweet/", {
  19. method: "POST",
  20. body: formData,
  21. headers: {
  22. 'X-CSRFToken': csrftoken,
  23. },
  24. })
  25. .then(response => response.json())
  26. .then(data => {
  27. console.log(tweetImageFile);
  28. if (tweetImageFile) {
  29. addPostToPage(tweet, `/media/tweet-pictures/${tweetImageFile.name}`, username);
  30. } else {
  31. addPostToPage(tweet, "", username);
  32. }
  33. clearPostSection();
  34. console.log(data.message);
  35. })
  36. .catch(error => {
  37. console.log(error);
  38. });
  39. }
  40. });

(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

  1. @csrf_exempt
  2. def post_tweet(request):
  3. if request.method == &quot;POST&quot;:
  4. print(request.FILES, request.POST)
  5. # Get contents of form
  6. tweet = request.POST.get(&quot;tweet&quot;, &quot;&quot;).strip()
  7. image = request.FILES.get(&quot;tweet_image&quot;)
  8. # Save the tweet to the model
  9. new_tweet = Tweet.objects.create(tweet=tweet, user=request.user, image=image)
  10. new_tweet.save()
  11. # Generate the URL for the uploaded image
  12. if image:
  13. image_url = settings.MEDIA_URL + str(image)
  14. else:
  15. image_url = None
  16. return JsonResponse({&quot;message&quot;: &quot;Tweet created successfully.&quot;, &quot;image_url&quot;: image_url}, status=201)
  17. else:
  18. return JsonResponse({&quot;error&quot;: &quot;POST request required.&quot;}, status=400)

posts.js

  1. const tweetForm = document.querySelector(&quot;#tweet-form&quot;);
  2. tweetForm.addEventListener(&#39;submit&#39;, function(event) {
  3. event.preventDefault();
  4. // Stops other event listeners of the same type of being called
  5. event.stopImmediatePropagation();
  6. const tweetInput = document.getElementById(&quot;post-content&quot;);
  7. const tweet = tweetInput.value;
  8. const tweetImageElement = document.querySelector(&quot;#tweet-picture&quot;);
  9. // Access the selected file and if there isn&#39;t any files, an empty string
  10. const tweetImageFile = tweetImageElement.files[0] ? tweetImageElement.files[0]: &quot;&quot;;
  11. const userNameInput = document.querySelector(&quot;#tweet-username&quot;);
  12. const username = userNameInput.value;
  13. if (tweet.trim().length &gt; 0) {
  14. const csrftoken = getCookie(&#39;csrftoken&#39;);
  15. const formData = new FormData();
  16. formData.append(&#39;tweet&#39;, tweet); // Add tweet content to FormData
  17. formData.append(&#39;tweet_image&#39;, tweetImageFile); // Add image file to FormData
  18. fetch(&quot;/post_tweet/&quot;, {
  19. method: &quot;POST&quot;,
  20. body: formData,
  21. headers: {
  22. &#39;X-CSRFToken&#39;: csrftoken,
  23. },
  24. })
  25. .then(response =&gt; response.json())
  26. .then(data =&gt; {
  27. console.log(tweetImageFile);
  28. if (tweetImageFile) {
  29. addPostToPage(tweet, `/media/tweet-pictures/${tweetImageFile.name}`, username);
  30. } else {
  31. addPostToPage(tweet, &quot;&quot;, username);
  32. }
  33. clearPostSection();
  34. console.log(data.message);
  35. })
  36. .catch(error =&gt; {
  37. console.log(error);
  38. });
  39. }
  40. });

huangapple
  • 本文由 发表于 2023年6月22日 02:38:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526225.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定