如何在Django同一视图中处理两个POST请求且避免MultiValueDictKeyError?
解决MultiValueDictKeyError:让视图兼容搜索和收藏两个POST请求
问题根源分析
你的问题出在两个核心点上:
- 收藏表单提交目标错误:页面里收藏按钮的
<form>没有指定action属性,默认会提交到当前页面的URL(也就是/search,对应search视图)。但search视图里直接用request.POST['search']获取搜索参数,收藏请求里根本没有这个参数,自然触发了MultiValueDictKeyError。 - 搜索视图参数获取不健壮:直接用字典下标
[]访问POST参数,一旦参数不存在就会报错,应该用更安全的写法。
分步解决方案
1. 修正收藏表单的提交目标
首先确保urls.py给anime视图设置好命名URL,方便模板调用:
# urls.py from django.urls import path from . import views urlpatterns = [ path('search/', views.search, name='search'), path('anime/add/', views.anime, name='add-anime-to-wishlist'), ]
然后修改HTML里的收藏表单,指定action为上述命名URL,同时修正原代码里的标签嵌套错误:
{% if user.is_authenticated %} {% if animes %} {% for anime in animes %} <form method="post" action="{% url 'add-anime-to-wishlist' %}"> {% csrf_token %} <section> <div class="row"> <div class="col-md-4 col-sm-6 col-lg-3"> <div class="card"> <div class="card-body text-center"> <p class="card-title"><b>{{anime.Title}}</b></p> <hr> <p class="card-text">Episodes: <b>{{anime.Episodes}}</b></p> <img src="{{anime.Image}}" /> </div> </div> <input type="hidden" value="{{anime.Id}}" name="anime_id"> <button type="submit" class="btn btn-outline-primary" style="font-size:18px; border-radius: 50%">★</button> </div> </div> </section> </form> {% endfor %} {% endif %} {% endif %}
2. 让搜索视图的参数获取更安全
把search视图里直接取request.POST['search']的写法,改成用get()方法,避免参数缺失时报错:
def search(request): animes = [] if request.method == 'POST': # 安全获取搜索参数,默认值为空字符串 search_query = request.POST.get('search', '') if search_query: # 只有搜索内容非空时才发起API请求 animes_url = 'https://api.jikan.moe/v3/search/anime' search_params = { 'q': search_query, 'limit': 6, 'page': 1 } r = requests.get(animes_url, params=search_params) results = r.json().get('results', []) for result in results: animes_data = { 'Id' : result["mal_id"], 'Title' : result["title"], 'Episodes' : result["episodes"], 'Image' : result["image_url"] } animes.append(animes_data) else: # 把提示消息传到模板显示,而不是用print messages.info(request, "请输入搜索关键词") context = { 'animes' : animes } return render(request,'search.html', context)
3. 优化收藏视图的容错性
anime视图里直接用Anime.objects.get(id=anime_id)可能触发DoesNotExist异常,加上容错处理更稳妥:
from django.shortcuts import get_object_or_404 def anime(request): if request.method == "POST": anime_id = request.POST.get("anime_id") # 找不到对应Anime时返回404,避免崩溃 anime = get_object_or_404(Anime, id=anime_id) request.user.profile.animes.add(anime) messages.success(request, f'{anime} added to wishlist.') return redirect('search') # 用URL名称重定向,更健壮 # GET请求访问时直接跳回搜索页 return redirect('search')
额外小提醒
- 注意HTML标签的闭合顺序,原代码里的嵌套错误可能导致页面布局异常;
- 调用外部API时建议加上网络请求、JSON解析的异常处理,避免视图因外部服务故障崩溃。
内容的提问来源于stack exchange,提问作者dazai
相关产品推荐
相关产品推荐

