Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MultiValueDictKeyError generated in Django after POST request on login page

I'm trying to build a login page. I'm running Django 1.6.1. I've largely been following the tutorial at www.fir3net.com/Django/django.html. For convenience I will repost a lot of it here.

Error Message:

Request Method: GET
Request URL: http://127.0.0.1:8000/login/

Database In Use: SQLite3 

Django Version: 1.6.1
Python Version: 2.7.4
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.contenttypes',
 'bookmarks')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.RemoteUserMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')


Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  114.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/tatenda/Documents/Programming/Django/Progs/django_bookmarks/bookmarks/views.py" in login_user
  17.   username = request.POST['username']
File "/usr/local/lib/python2.7/dist-packages/django/utils/datastructures.py" in __getitem__
  301.             raise MultiValueDictKeyError(repr(key))

Exception Type: MultiValueDictKeyError at /login/
Exception Value: "'username'"

View Code (I understand that several of the import functions called here are superfluous to my immediate problem. Mostly they are redundant code from trying to follow previous tutorials on how to do this):

from django.http import*
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.template import Context
from django.template.loader import get_template
from django.http import HttpResponse, Http404
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.contrib.auth.decorators import login_required

def login_user(request):

    username = password = ''
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password = password)
    if user is not None:
        if user.is_active:
            login(request, user)
            return HttpResponseRedirect('/main_page/')
    return render_to_response('base.html', context_instance = RequestContext(request))

@login_required(login_url = '/login/')
def main_page(request):
    template = get_template('main_page.html')
    variables = Context ({
        'head_title':'Django Bookmarks',
        'page_title':'Welcome to Django Bookmarks',
        'page_body':'Where you store and share bookmarks!'
    })
    output = template.render(variables)
    return HttpResponse(output)

def user_page(request, username):
    try:
        user = User.objects.get(username=username)
    except:
        raise Http404('Requested user not found.')

    bookmarks = user.bookmark_set.all()
    template = get_template('user_page.html')
    variables = Context({
        'username':username,
        'bookmarks': bookmarks
    })
    output = template.render(variables)
    return HttpResponse(output)

@csrf_exempt
def login_page(request):

    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request,user)
            template = get_template('main_page.html')
            variables = Context ({
                'head_title':'Django Bookmarks',
                'page_title':'Welcome to Django Bookmarks',
                'page_body':'Where you store and share bookmarks!'
            })
            output = template.render(variables)
            return HttpResponse(output)
        else:
            raise Http404('Disabled account, please contact administrator.')
    else:
        raise Http404('Invalid login.')

Info from urls.py file:

from django.conf.urls import patterns, include, url
from django.contrib import admin
from bookmarks.views import*

admin.autodiscover()

urlpatterns = patterns('',
    (r'^$', main_page),
    (r'^user/(\w+)/$', user_page),
    url(r'^login/$', login_user),
)

Base Template Used to Create Login Page (the file is named base.html):
Note - the CSS styling is bootstrap based

<!DOCTYPE html>
<html>
    <head>
        {% block head %}
            <link rel = "stylesheet" href = "style.css" />
            <title> {% block title %}{% endblock %} - My Webpage</title></div>
        {% endblock %}
    </head>
    <body>
        <div id = "content">{% block content %}{% endblock %}</div>
        <div id = "footer">
            {% block footer %}
                &copy; Copyright 2011 by <a href="http://domain.invalid/">you</a>
            {% endblock %}
        </div>
    </body>
</html>

HTML Code for the Login Page (the file is named login.html):

{% extends "base.html" %}
{% block main %}
    <div id = "login">
        <form class = "form-horizontal" name = "LoginForm" action = "/login/" method = "post">
        {% csrf_token %}
        {% if next %}
            <input type = "hidden" name = "next" value = "{{ next }}" />
        {% endif %}
        <div class = "control-group">
            <label class = "control-label" for = "username">Username</label>
            <div class = "controls">
                <input type = "text" id = "username" placeholder = "Username">
            </div>
        </div>
        <div class = "control-group">
            <label class = "control-label" for = "password">Password</label>
            <div class = "controls">
                <input type = "password" name = "password" id = "password" placeholder = "Password">
            </div>
        </div>
        <div class = "control-group">
            <div class = "controls">
                <button type = "submit" class = "btn">Login</button>
            </div>
        </div>
        </form>
    </div>
{% endblock %}
like image 439
PyUnchained Avatar asked Dec 23 '13 02:12

PyUnchained


People also ask

How do I fix MultiValueDictKeyError?

To fix the Python Django MultiValueDictKeyError error, we use the dictionary get method to get the dict value and return a default if the dict key doesn't exist. to call get on request. POST to get the is_private dict value from the POST request payload. And if is_private wasn't sent, then we return False .

What is multi value DICT key error Django?

This is specific to Django. The method get() returns a value for the given key if key is in the dictionary. If key is not available then returns default value None. You can handle this error by putting : is_private = request.POST.get('is_private', False);

How do I see POST requests in Django?

When a POST request is received at the Django server, the data in the request can be retrieved using the HTTPRequest. POST dictionary. All the data of the POST request body is stored in this dictionary. For example, you can use the following code snippet inside your view.py file.

What does _() mean in Django?

_ in Django is a convention that is used for localizing texts. It is an alias for ugettext_lazy.


3 Answers

I had the same error, and i did this and it worked. Change:

username = request.POST['username']
password = request.POST['password'] 

to:

username = request.POST.get('username')
password = request.POST.get('password')

The above handles both the POST and GET methods that may result. I hope this helped.

like image 171
Emack333 Avatar answered Oct 19 '22 06:10

Emack333


When a request resolves to a view that's wrapped with the @login_required decorator, the request is redirected to the specified URL if the user is not logged in. So attempting to resolve your main_page view while not logged in will cause the user's browser to issue a GET request to /login/. However, the view that handles that URL assumes a POST request:

username = request.POST['username']
password = request.POST['password']

The usual approach would be to follow the general pattern for using a form in a view: https://docs.djangoproject.com/en/dev/topics/forms/#using-a-form-in-a-view

Specifically, check the request.method attribute so you can behave appropriately on a GET request and render the form. Or use the built-in views, they're pretty easy to work with.

like image 27
Peter DeGlopper Avatar answered Oct 19 '22 04:10

Peter DeGlopper


I was able to suppress error by following @Emack333 but then, the code on views.py was not working and then upon close inspection, I've found that error was not on view file, rather it was on HTML side.

This error got generated because there was a mismatch of name attribute on the HTML input tag and in your case, it was name attr is missing.

<input type = "text" id = "username" placeholder = "Username" name="username">
like image 1
MastermanSachin Avatar answered Oct 19 '22 05:10

MastermanSachin