Django CRM新增记录触发MultiValueDictKeyError及登录失败异常
Django CRM新增记录异常问题
完成FreeCodeCamp的Django CRM教程后,在新增记录页面遇到以下问题:
- 初始报错:终端返回
Internal Server Error,触发MultiValueDictKeyError: 'username',错误指向views.py的home函数中request.POST['username']代码行。 - 修改后问题:将代码改为
request.POST.get('username')后,新增记录时直接弹出login failed提示,但登录功能可正常使用,仅新增记录时出现该问题。
终端错误栈
Internal Server Error: / Traceback (most recent call last): File "C:\Users\desktop\personaldump\python\django\virt\lib\site-packages\django\utils\datastructures.py", line 84, in __getitem__ list_ = super().__getitem__(key) KeyError: 'username' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\desktop\personaldump\python\django\virt\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "C:\Users\desktop\personaldump\python\django\virt\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "C:\Users\desktop\personaldump\python\django\virt\Scripts\CRM\first\views.py", line 10, in home username=request.POST['username'] File "C:\Users\desktop\personaldump\python\django\virt\lib\site-packages\django\utils\datastructures.py", line 86, in __getitem__ raise MultiValueDictKeyError(key) django.utils.datastructures.MultiValueDictKeyError: 'username' [02/May/2023 23:40:34] "POST / HTTP/1.1" 500 81254
修改前后的views.py代码
修改前
def home(request): records= Record.objects.all() if request.method=='POST': username=request.POST['username'] password=request.POST['password'] user=authenticate(request,username=username, password=password) if user is not None: login(request,user) messages.success(request,"login successful") return redirect('home') else: messages.success(request, "login failed") return redirect('home') return render(request,'home.html',{'records':records})
修改后
def home(request): records= Record.objects.all() if request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') user=authenticate(request,username=username, password=password) if user is not None: login(request,user) messages.success(request,"login successful") return redirect('home') else: messages.success(request, "login failed") return redirect('home') return render(request,'home.html',{'records':records})
home.html代码
{%extends 'base.html'%} {%block content%} {%if user.is_authenticated%} <h1>Records</h1> <table class="table table-striped table-hover table-bordered"> <thead class="table-dark"> <tr> <th scope="col">Name</th> <th scope="col">Email</th> <th scope="col">Phone</th> <th scope="col">Address</th> <th scope="col">City</th> <th scope="col">State</th> <th scope="col">Zipcode</th> <th scope="col">Created At</th> <th scope="col">ID</th> </tr> </thead> <tbody> {% if records %} {% for record in records %} <tr> <td>{{ record.name }}</td> <td>{{ record.email }}</td> <td>{{ record.phone }}</td> <td>{{ record.address }}</td> <td>{{ record.city }}</td> <td>{{ record.state }}</td> <td>{{ record.zipcode }}</td> <td>{{ record.created_at }}</td> <td><a href="{% url 'record' record.id %}">{{ record.id }}</a></td> </tr> {% endfor %} {% endif %} </tbody> </table> {%else%} <div class="col-md-6 offset-md-3"> <h1>Login</h1> <form method="post" action="{%url 'home'%}"> {% csrf_token%} <div class="mb-3"> <input type="text" class="form-control" name="username", placeholder="Username" required> </div> <div class="mb-3"> <input type="password" class="form-control" name="password", placeholder="Password" required> </div> <br/> <button type="submit" class="btn btn-secondary">Login</button> </form> </div> {%endif%} {%endblock%}
addrecord.html代码
{%extends 'base.html'%} {%block content%} <div class="col-md-6 offset-md-3"> <h1>Add Record</h1> <form method="post" action="{%url 'home'%}"> {% csrf_token%} {{form.as_p}} <br/> <button type="submit" class="btn btn-secondary">ADD</button> </form> </div> {%endblock%}
forms.py代码
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from .models import Record from django import forms class Signup(UserCreationForm): email=forms.EmailField(label='',widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Email Address'})) FullName=forms.CharField(label='',max_length=100,widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Full Name'})) class Meta: model=User fields={'username','password1','password2','email','FullName'} def __init__(self,*args,**kwargs): super(Signup,self).__init__(*args,**kwargs) self.fields['username'].widget.attrs['class'] = 'form-control' self.fields['username'].widget.attrs['placeholder'] = 'User Name' self.fields['username'].label = '' self.fields['username'].help_text = '<span class="form-text text-muted"><small></br>Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</small></span>' self.fields['password1'].widget.attrs['class'] = 'form-control' self.fields['password1'].widget.attrs['placeholder'] = 'Password' self.fields['password1'].label = '' self.fields['password1'].help_text = '<ul class="form-text text-muted small"><li>Your password can\'t be too similar to your other personal information.</li><li>Your password must contain at least 8 characters.</li><li>Your password can\'t be a commonly used password.</li><li>Your password can\'t be entirely numeric.</li></ul>' self.fields['password2'].widget.attrs['class'] = 'form-control' self.fields['password2'].widget.attrs['placeholder'] = 'Confirm Password' self.fields['password2'].label = '' self.fields['password2'].help_text = '<span class="form-text text-muted"><small>Enter the same password as before, for verification.</small></span>' class AddRecordForm(forms.ModelForm): name = forms.CharField(required=True, widget=forms.widgets.TextInput(attrs={"placeholder":"Full Name", "class":"form-control"}), label="") email = forms.CharField(required=True, widget=forms.widgets.TextInput(attrs={"placeholder":"Email", "class":"form-control"}), label="") phone = forms.CharField(required=True, widget=forms.widgets.TextInput(attrs={"placeholder":"Phone", "class":"form-control"}), label="") address = forms.CharField(required=True, widget=forms.widgets.TextInput(attrs={"placeholder":"Address", "class":"form-control"}), label="") city = forms.CharField(required=True, widget=forms.widgets.TextInput(attrs={"placeholder":"City", "class":"form-control"}), label="") state = forms.CharField(required=True, widget=forms.widgets.TextInput(attrs={"placeholder":"State", "class":"form-control"}), label="") zipcode = forms.CharField(required=True, widget=forms.widgets.TextInput(attrs={"placeholder":"Zipcode", "class":"form-control"}), label="") class Meta: model = Record exclude = ("user",)
问题原因与解决方案
核心原因
新增记录表单的提交地址指向了home视图(action="{%url 'home'%}"),而home视图仅处理登录逻辑,未区分登录请求和新增记录请求。提交新增记录时,POST数据中没有username和password字段,导致:
- 使用
request.POST['username']会直接抛出MultiValueDictKeyError - 改用
request.POST.get('username')后,username为None,authenticate返回None,触发登录失败提示
解决方案
- 新增专门的新增记录视图:在
views.py中添加处理新增记录的函数
from .forms import AddRecordForm def add_record(request): if request.user.is_authenticated: if request.method == 'POST': form = AddRecordForm(request.POST) if form.is_valid(): form.save() messages.success(request, "记录已成功添加") return redirect('home') else: form = AddRecordForm() return render(request, 'addrecord.html', {'form': form}) else: messages.success(request, "请先登录") return redirect('home')
- 修改addrecord.html的表单提交地址:将表单
action指向新增视图
<form method="post" action="{%url 'add_record'%}">
- 配置URL路由:在
urls.py中添加新增记录的路由
from .views import home, add_record urlpatterns = [ path('', home, name='home'), path('add-record/', add_record, name='add_record'), # 其他路由... ]
- 优化home视图的登录逻辑:仅在用户未登录时处理登录请求,避免已登录用户提交POST时触发登录逻辑
def home(request): records= Record.objects.all() # 仅当用户未登录且请求为POST时处理登录 if not request.user.is_authenticated and request.method=='POST': username=request.POST.get('username') password=request.POST.get('password') user=authenticate(request,username=username, password=password) if user is not None: login(request,user) messages.success(request,"登录成功") return redirect('home') else: messages.error(request, "登录失败,请检查用户名和密码") return redirect('home') return render(request,'home.html',{'records':records})
修改后,登录与新增记录逻辑完全分离,各自处理对应POST请求,不再出现冲突。
内容的提问来源于stack exchange,提问作者Shaik Shahid Afridi
相关产品推荐
相关产品推荐

