Django登录页Remember Me未勾选触发MultiValueDictKeyError问题解决
问题:登录页面Remember Me未勾选时触发MultiValueDictKeyError
尝试为登录页面添加Remember Me选项,勾选该选项时登录流程正常,但未勾选时会触发MultiValueDictKeyError: 'remember'错误。
相关代码
forms.py
class Signin(forms.Form): username = forms.CharField( max_length=9, widget=forms.TextInput( attrs={ "id": "input_64", "name": "q64_typeA", "data-type": "input-textbox", "class": "form-textbox validate[required]", "data-defaultvalue": "", "size": "20", "placeholder": "180591001", "data-component": "textbox", "aria-labelledby": "label_64", "required": "", } ), ) password = forms.CharField( max_length=255, widget=forms.PasswordInput( attrs={ "id": "first_66", "name": "q66_name66[first]", "class": "form-textbox validate[required]", "data-defaultvalue": "", "autoComplete": "section-input_66 given-name", "size": "10", "data-component": "first", "aria-labelledby": "label_66 sublabel_66_first", "required": "", "placeholder": "•••••••••••••••", } ), ) remember = forms.BooleanField(required=False, initial=False)
views.py
def signin(request): if request.user.is_authenticated: return redirect(index) if request.method == "POST": form = Signin(request.POST) if form.is_valid(): username = request.POST["username"] password = request.POST["password"] remember = request.POST["remember"] user = User.objects.filter(username=username).exists() if user: get_user = User.objects.filter(username=username) check_pass = check_password(password, get_user[0].password) if not check_pass: messages.error(request, "incorrect password") return redirect(signin) else: login(request, get_user[0]) if not remember: request.session.set_expiry(0) return redirect(index) else: messages.error(request, "Invalid User") return redirect(signin) else: form = Signin() return render(request, "accounts/login.html", {"form": form})
模板代码
<form class="jotform-form" action="/signin/" method="post" enctype="multipart/form-data" name="form_230023299150548" id="230023299150548" accept-charset="utf-8" autocomplete="on"> {% csrf_token %} <div role="main" class="form-all"> <ul class="form-section page-section"> <li id="cid_60" class="form-input-wide" data-type="control_head"> <div class="form-header-group header-small"> <div class="header-text httal htvam"> <h3 id="header_60" class="form-header" data-component="header">SignIn</h3> </div> </div> </li> <li class="form-line jf-required" data-type="control_textbox" id="id_64"> <label class="form-label form-label-left" id="label_64" for="input_64"> Username <span class="form-required">*</span> </label> <div id="cid_64" class="form-input jf-required"> {{form.username}} </div> </li> <li class="form-line jf-required" data-type="control_fullname" id="id_66"> <label class="form-label form-label-left form-label-auto" id="label_66" for="first_66">Password <span class="form-required">*</span> </label> <div id="cid_66" class="form-input jf-required"> <div data-wrapper-react="true"> <span class="form-sub-label-container" style="vertical-align:top" data-input-type="first"> {{form.password}} </span> </div> </li> <li class="form-line jf-required" data-type="control_fullname" id="id_90"> <label class="form-label form-label-left form-label-auto" id="label_90" for="first_90">Remember Me </label> <div id="cid_90" class="form-input jf-required"> <div data-wrapper-react="true"> <span class="form-sub-label-container" style="vertical-align:top" data-input-type="first"> {{form.remember}} </span> </div> </li> <li class="form-line" data-type="control_button" id="id_76"> <div id="cid_76" class="form-input-wide"> <div data-align="center" class="form-buttons-wrapper form-buttons-center jsTest-button-wrapperField"><button id="input_76" type="submit" class="form-submit-button submit-button jf-form-buttons jsTest-submitField" data-component="button" data-content="">Submit</button></div> </div> </li> </ul> </form>
错误信息
MultiValueDictKeyError at /signin/ 'remember' Request Method: POST Request URL: http://localhost:8002/signin/ Django Version: 4.1.2 Exception Type: MultiValueDictKeyError Exception Value: 'remember' Exception Location: /home/dubsy/virtualenvs/djangoproject/lib/python3.9/site-packages/django/utils/datastructures.py, line 86, in __getitem__ Raised during: accounts.views.signin Python Executable: /home/dubsy/virtualenvs/djangoproject/bin/python Python Version: 3.9.12
修复方案
核心原因
HTML表单中,未勾选的复选框不会被提交到后端,直接通过request.POST['remember']取值会触发键不存在的错误。
方案1:使用request.POST.get()安全取值
修改views.py中获取remember的代码,用get()方法指定默认值:
remember = request.POST.get('remember', False)
该方法会在键不存在时返回默认值False,避免报错。
方案2:使用表单cleaned_data(推荐)
既然已经使用Django表单,直接从验证后的表单数据中取值更规范,表单会自动处理布尔字段的默认值:
def signin(request): if request.user.is_authenticated: return redirect(index) if request.method == "POST": form = Signin(request.POST) if form.is_valid(): # 从表单cleaned_data中获取验证后的值 username = form.cleaned_data['username'] password = form.cleaned_data['password'] remember = form.cleaned_data['remember'] # 优化查询:用first()替代filter()[0],避免索引错误 user = User.objects.filter(username=username).first() if user: check_pass = check_password(password, user.password) if not check_pass: messages.error(request, "incorrect password") return redirect(signin) else: login(request, user) if not remember: request.session.set_expiry(0) return redirect(index) else: messages.error(request, "Invalid User") return redirect(signin) else: form = Signin() return render(request, "accounts/login.html", {"form": form})
额外优化
- 模板中Remember Me对应的li标签去掉
jf-required类,因为该选项是非必填的:
<li class="form-line" data-type="control_fullname" id="id_90">
内容的提问来源于stack exchange,提问作者Olasubomi
相关产品推荐
相关产品推荐

