Django中json.loads(request.body)报JSONDecodeError问题求助
Fixing JSONDecodeError in Django updateItem View
Let's break down your problem and fix it step by step:
Root Cause Analysis
The error JSONDecodeError at /update_item/ Expecting value: line 1 column 1 (char 0) happens for three key reasons:
- Request is sent as GET instead of POST: Your frontend code specifies
method: 'POST', but the error log shows the request method is GET. This usually means the CSRF token validation failed, causing Django to reject the POST request (or redirect it to a GET). - Empty request body: GET requests don't include a request body, so
json.loads(request.body)tries to parse an empty string, triggering the decode error. - Unhandled anonymous user: Your code assumes
request.user.customerexists, but forAnonymousUser, this will throw an error even if you fix the JSON parsing issue.
Step 1: Fix CSRF Token Retrieval in Frontend
Your frontend uses csrftoken but doesn't show how it's fetched. Django requires the CSRF token for POST requests, so add this function to properly retrieve it from cookies:
function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } // Initialize csrftoken correctly const csrftoken = getCookie('csrftoken'); function updateUserOrder(productId, action) { console.log('User authentication status:', request.user.is_authenticated); var url = '/update_item/' fetch(url, { method: 'POST', headers: { "Content-Type": 'application/json', 'X-CSRFToken': csrftoken, }, body: JSON.stringify({'productId': productId, 'action': action}) }) .then((response) => { if (!response.ok) throw new Error('Request failed'); return response.json() }) .then((data) => { console.log('Data: ', data) location.reload() }) .catch(error => console.error('Error:', error)); }
Step 2: Secure and Robustify the Django View
Update your updateItem view to handle POST requests only, validate JSON input, and support anonymous users with session-based cart storage:
import json from django.http import JsonResponse from .models import Product, Order, OrderItem def updateItem(request): # Reject non-POST requests immediately if request.method != 'POST': return JsonResponse({'error': 'Only POST requests are allowed'}, status=400) # Safely parse JSON data try: data = json.loads(request.body) except json.JSONDecodeError: return JsonResponse({'error': 'Invalid or empty JSON data'}, status=400) # Validate required fields product_id = data.get('productId') action = data.get('action') if not product_id or not action in ['add', 'remove']: return JsonResponse({'error': 'Missing or invalid required fields'}, status=400) # Handle anonymous users with session-based cart if request.user.is_anonymous: cart = request.session.get('cart', {}) if action == 'add': cart[product_id] = cart.get(product_id, 0) + 1 elif action == 'remove': if product_id in cart: cart[product_id] -= 1 if cart[product_id] <= 0: del cart[product_id] # Save cart to session request.session['cart'] = cart return JsonResponse('Item updated in session cart', safe=False) # Handle authenticated users try: customer = request.user.customer product = Product.objects.get(id=product_id) order, created = Order.objects.get_or_create(customer=customer, complete=False) order_item, created = OrderItem.objects.get_or_create(product=product, order=order) if action == 'add': order_item.quantity += 1 elif action == 'remove': order_item.quantity -= 1 order_item.save() if order_item.quantity <= 0: order_item.delete() return JsonResponse('Item was updated', safe=False) except Product.DoesNotExist: return JsonResponse({'error': 'Product not found'}, status=404) except Exception as e: return JsonResponse({'error': str(e)}, status=500)
Step 3: Verify URL Configuration
Ensure your urls.py maps the /update_item/ path correctly without conflicting GET routes:
from django.urls import path from . import views urlpatterns = [ # ... other URLs path('update_item/', views.updateItem, name='update_item'), ]
Step 4: Debug the Request
Open your browser's DevTools (Network tab) to confirm:
- The request method is POST (not GET)
- The CSRF token is present in request headers
- The request body contains the expected JSON payload (
{"productId": "...", "action": "..."})
内容的提问来源于stack exchange,提问作者Muskan Kalra
相关产品推荐
相关产品推荐

