You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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字段,导致:

  1. 使用request.POST['username']会直接抛出MultiValueDictKeyError
  2. 改用request.POST.get('username')后,username为None,authenticate返回None,触发登录失败提示

解决方案

  1. 新增专门的新增记录视图:在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')
  1. 修改addrecord.html的表单提交地址:将表单action指向新增视图
<form method="post" action="{%url 'add_record'%}">
  1. 配置URL路由:在urls.py中添加新增记录的路由
from .views import home, add_record

urlpatterns = [
    path('', home, name='home'),
    path('add-record/', add_record, name='add_record'),
    # 其他路由...
]
  1. 优化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:47:03