Django 导航键错误

Django Navigation Key Error

我有一个关于 Django 导航栏的问题。我以前曾获得有关如何修复 tags.py 的帮助,但现在我收到一条错误消息:

Exception Type:     KeyError
Exception Value:    'request' 
Exception Location:     /usr/lib/python2.7/site-packages/django/template/context.py in __getitem__, line 70
Python Executable:  /usr/bin/python  

我被告知要添加

TEMPLATE_CONTEXT_PROCESSORS =  (
        'django.core.context_processors.request',
        'django.contrib.auth.context_processors.auth'
        )

在我的 settings.py 文件中,但错误仍然存​​在。

## file path
-- Main project folder
  -- manage.py
  -- .. other files ..
  -- src
     -- urls.py
     -- settings.py
     -- .. other files ..
  -- templates
     -- base.html
  -- app folder
    -- templates
       -- app name
          -- index.html
          -- login.html
          -- register.html
    -- templatetags
      -- __init__.py
      -- tags.py

## urls.py
from django.conf.urls import patterns, url

from game import views

urlpatterns = patterns('',
    url(r'^$', views.index, name='index'),
    url(r'^upload/$', views.upload_file, name='upload'),
    url(r'^successful_upload/$', views.successful_upload, name='successful_upload'),
    url(r'^play/$', views.play, name='play'),
    url(r'^registration/$', views.register, name='register'),
    url(r'^successful_registeration/$', views.successful_registeration, name='successful_registeration'),
    url(r'^login/$', views.login, name='login'),
    url(r'^logout/$', views.logout, name='logout')
)

## tags.py
from django import template

register = template.Library()

@register.tag
def active(parser, token):
    import re
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:])

class NavSelectedNode(template.Node):
    def __init__(self, patterns):
        self.patterns = patterns
    def render(self, context):
        path = context['request'].path
        for p in self.patterns:
            pValue = template.Variable(p).resolve(context)
            if path == pValue:
                return "-active"
        return ""

## base.html
{% load tags %}
{% url 'index' as home %}
{% url 'upload' as upload %}
{% url 'play' as play %}
{% url 'register' as contact %}
{% url 'login' as login %}

<div id="navigation">
    <a class="{% active request home %}" href="{{ home }}">Home</a>
    <a class="{% active request upload %}" href="{{ upload }}">Upload</a>
    <a class="{% active request play %}" href="{{ play }}">Play</a>
    <a class="{% active request contact %}" href="{{ contact }}">Contact</a>
    <a class="{% active request login %}" href="{{ login }}">Login</a>
</div>

## login.html
{% extends "base.html" %}
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="/game/login/" method="post">
{% csrf_token %}
<table border='0'>
<div class="fieldWrapper"><tr><td>
        {{ form.user_name.errors }}</td><td></td></tr><tr><td>
        <label for="id_user_name">User Name:</label></td><td>
        {{ form.user_name }}</td></tr>
    </div>
    <div class="fieldWrapper"><tr><td>
        {{ form.password.errors }}</td><td></td><tr><td>
        <label for="id_password">Password:</label></td><td>
        {{ form.password }}</td></tr>
    </div>
</table>
<input type="submit" value="Login" />
</form>

## settings.py
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'xz6e)1=!%wma16h9$lt&gl8(96^(@1t2n)&lesteje_%x$+jn^'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

TEMPLATE_DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'game',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'wam.urls'

WSGI_APPLICATION = 'wam.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'America/Chicago'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/

STATIC_URL = '/static/'

TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]

from django.conf import global_settings

TEMPLATE_CONTEXT_PROCESSORS =  (
    'django.core.context_processors.request',
    'django.contrib.auth.context_processors.auth'
)

# views.py

from django.shortcuts import render, render_to_response
from django.http import HttpResponse, HttpResponseRedirect
from django.core.context_processors import csrf
from django.http import Http404

from forms import UploadFileForm, UserRegisterForm, UserLoginForm
from game.models import UserLogin

def handle_uploaded_file(f, n):
    with open('ais/' + n + '.py', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

# Create your views here.
def index(request):
    return HttpResponse("Hello, world. You're at the game index.")

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            post = request.POST
            files = request.FILES
            handle_uploaded_file(files['player1_ai_code'],
                                 post['player1_ai_title'])
            handle_uploaded_file(files['player2_ai_code'],
                                 post['player2_ai_title'])
            return HttpResponseRedirect('/game/successful_upload')
    else:
        form = UploadFileForm()
    c = {'form': form}
    c.update(csrf(request))
    return render_to_response('game/upload.html', c)

def successful_upload(request):
    return HttpResponse("The two ai's were successfully upload.")

def play(request):
    import sys
    sys.path.insert(0, 'ais')
    sys.path.insert(0, '../tictactoe/')
    import tictactoe
    from html_change import *
    s = tictactoe.play_game(ai=['ai1', 'randai'])
    return HttpResponse(change(s))

def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            post = request.POST
            # check if the user exists in the database
            check_user_exists = UserLogin.objects.filter(user_name=post['user_name'])
            if check_user_exists:
                c = {'form': form,
                     'error_message': "This user name already exists."}
                c.update(csrf(request))
                return render_to_response('game/register.html', c)
            # check size of user name
            if len(post['user_name']) < 5:
                c = {'form': form,
                     'error_message': "Your username must be longer than 5 characters."}
                c.update(csrf(request))
                return render_to_response('game/register.html', c)
            # check size of password
            if len(post['password']) < 5:
                c = {'form': form,
                     'error_message': "Your password must be longer than 5 characters."}
                c.update(csrf(request))
                return render_to_response('game/register.html', c)
            # check if passwords match -- for the form
            if post['password'] != post['re_password']:
                c = {'form': form,
                     'error_message': "Your passwords do not match"}
                c.update(csrf(request))
                return render_to_response('game/register.html', c)
            # registeration successful
            user = UserLogin(user_name=post['user_name'], password=post['password'])
            user.save()
            return HttpResponseRedirect('/game/successful_registeration')
    else:
        form = UserRegisterForm()
    c = {'form': form}
    c.update(csrf(request))
    return render_to_response('game/register.html', c)

def successful_registeration(request):
    return HttpResponse("Your registration was successful")

def login(request):
    if request.method == 'POST':
        form = UserLoginForm(request.POST)
        if form.is_valid():
            m = UserLogin.objects.get(user_name=request.POST['user_name'])
            if m.password == request.POST['password']:
                request.session['member_id'] = m.id
                return  HttpResponseRedirect('/game')
            else:
                c = {'form': form,
                     'error_message': "Your username and password didn't match."}
                c.update(csrf(request))
                return render_to_response('game/login.html', c)
    else:
        form = UserLoginForm()
    c = {'form': form}
    c.update(csrf(request))
    return render_to_response('game/login.html', c)

def logout(request):
    try:
        del request.session['member_id']
    except KeyError:
        pass
    return HttpResponseRedirect("/game")

您应该在 settings.py 文件中从 django.conf.global_settings 导入 TEMPLATE_CONTEXT_PROCESSORS 而不是定义一个新文件:

settings.py

from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
...
TEMPLATE_CONTEXT_PROCESSORS += ('django.core.context_processors.request',)
...

此外,上下文处理器仅适用于 RequestContext 实例,因此您应该检查视图并确保使用 RequestContext 实例渲染模板:

from django.template import RequestContext

return render_to_response('base.html', {}, request_context=RequestContext(request))

甚至更好,使用render快捷功能:

from django.shortcuts import render

return render(request, 'base.html')

有关模板中上下文变量的详细信息,请参阅 documentation