如何使用 google 应用引擎数据存储区 (NDB) 配置 Django 会话

How to configure Django session with google app engine datastore (NDB)

这是我尝试使用会话时遇到的错误 request.session['user'] = user

ImproperlyConfigured at /registration/
settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.

这是 view.py 函数,我在其中出错

@csrf_exempt
@require_POST
def registration(request):
    form    =   regi_form(request.POST)
    if form.is_valid():        
        email_key = generate_email_key()
        try:
            send_activ_mail( to = form.cleaned_data['email'],key = email_key )
        except Exception,e:
            print '@registration %s'%e
        user = User(
            name=                 form.cleaned_data['name'],
            email=                form.cleaned_data['email'],
            password=             make_password(password=form.cleaned_data['password'], salt=None, hasher='default'),
            last_login=           datetime.now(),
            email_activation_key= email_key,
            email_active=         False,
            )
        user.put()
        request.session['user'] = user
        response = {
                        'meta'      : { 'message' : 'Registered' , 'enum' : 'Ok' },
                        'payload'   : { 'user' : {'name' : user.name } }
                    }
        return HttpResponse(json.dumps(response),content_type="application/json")
    else:
        errors_dict = {}
        if form.errors:
            for error in form.errors:
                e = form.errors[error]
                str_remove = str(e)
                str_need = re.search('<li>(.+?)</li>', str_remove).group(1)
                errors_dict[error] = unicode(str_need)
            return HttpResponseBadRequest(json.dumps(errors_dict), content_type="application/json")

我跟着To use NDB with the Django web framework添加了中间件

'google.appengine.ext.ndb.django_middleware.NdbDjangoMiddleware',

但是关于会话没有任何解释 所以我在 setting.py

中将其留空 DATABASE = {}

Setting.py

# Django settings for tradex_plus project.


DEBUG = True
TEMPLATE_DEBUG = DEBUG

import os

PROJECT_DIR = os.path.dirname(__file__)

BASE_DIR = os.path.dirname(os.path.dirname(__file__))

# gives the root of the project: root/. This is THE ROOT OF THE PROJECT
PROJECT_PATH = os.path.abspath(os.path.dirname(__name__))

# import sys
# sys.path.insert(0, os.path.join(BASE_DIR, "lib/python2.7/site-packages/") )



ADMINS = (
    # ('Your Name', 'your_email@example.com'),
)

MANAGERS = ADMINS



# Hosts/domain names that are valid for this site; required if DEBUG is False
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
ALLOWED_HOSTS = []

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'America/Chicago'

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'

SITE_ID = 1

# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/var/www/example.com/media/"
MEDIA_ROOT = ''

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://example.com/media/", "http://media.example.com/"
MEDIA_URL = ''

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

STATIC_URL = '/frontend/'

# STATIC_ROOT = os.path.join(BASE_DIR, "fronten")

FRONTEND = os.path.join(BASE_DIR, "frontend")

STATICFILES_DIRS = (
    FRONTEND,

)

STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    # 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
   # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)


# Make this unique, and don't share it with anybody.
SECRET_KEY = 'c94coq2ly9*y*j@-l!a)eeubf)17i0yy)=lrkm-h#da@!v96ot'

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
#     'django.template.loaders.eggs.Loader',
)

TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    os.path.join(BASE_DIR, "frontend"),
)

MIDDLEWARE_CLASSES = (
    'google.appengine.ext.ndb.django_middleware.NdbDjangoMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'tradex_plus.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'tradex_plus.wsgi.application'


INSTALLED_APPS = (
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.staticfiles',    
    'user_module',
)

# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}

DATABASES = {}

调试器returns这个

   mproperlyConfigured at /registration/
settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.

Request Method: POST
Request URL: http://localhost:8080/registration/
Django Version: 1.5.8
Python Executable: /usr/bin/python
Python Version: 2.7.6
Python Path: ['/Users/foodprinting/proj/tradex-plus', '/Users/foodprinting/google-cloud-sdk/platform/google_appengine', '/Users/foodprinting/google-cloud-sdk/platform/google_appengine', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload', '/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5', '/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/protorpc-1.0', '/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.3', '/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/webob-1.1.1', '/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/yaml-3.10']
Server time: Fri, 27 Feb 2015 10:46:26 +0000
Installed Applications:
('django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.staticfiles',
 'user_module')
Installed Middleware:
('google.appengine.ext.ndb.django_middleware.NdbDjangoMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')

Traceback:
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/core/handlers/base.py" in get_response
  185.                 response = middleware_method(request, response)
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/contrib/sessions/middleware.py" in process_response
  38.                     request.session.save()
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/contrib/sessions/backends/db.py" in save
  50.             session_key=self._get_or_create_session_key(),
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/contrib/sessions/backends/base.py" in _get_or_create_session_key
  147.             self._session_key = self._get_new_session_key()
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/contrib/sessions/backends/base.py" in _get_new_session_key
  141.             if not self.exists(session_key):
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/contrib/sessions/backends/db.py" in exists
  26.         return Session.objects.filter(session_key=session_key).exists()
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/db/models/query.py" in exists
  610.             return self.query.has_results(using=self.db)
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/db/models/sql/query.py" in has_results
  447.         return bool(compiler.execute_sql(SINGLE))
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/db/models/sql/compiler.py" in execute_sql
  836.             sql, params = self.as_sql()
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/db/models/sql/compiler.py" in as_sql
  74.         out_cols = self.get_columns(with_col_aliases)
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/db/models/sql/compiler.py" in get_columns
  174.         result = ['(%s) AS %s' % (col[0], qn2(alias)) for alias, col in six.iteritems(self.query.extra_select)]
File "/Users/foodprinting/google-cloud-sdk/platform/google_appengine/lib/django-1.5/django/db/backends/dummy/base.py" in complain
  15.     raise ImproperlyConfigured("settings.DATABASES is improperly configured. "

Exception Type: ImproperlyConfigured at /registration/
Exception Value: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.
Request information:
GET: No GET data

POST:
re_password = u'hungrymind'
name = u'praveen'
password = u'hungrymind'
email = u'prrraveen@gmail.com'

FILES: No FILES data

COOKIES:
_tinyowl_session = 'BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWYyYTY0ZmVjYjQxMmNlOWE0M2I2ZTMyYWE5OTgzZjI0BjsAVEkiEnNlc3Npb25fdG9rZW4GOwBGSSJgNzE5ckJnZ3hDaEZLTlRIdnViM0NXSmJFTFhvQUc4OTJNaWVTcTNGSmZGUlVWdG9DeDBSN1JTU2tXc0hUWTlxbUNXQ05DekNqSXZNdUw1MXBVV2xsZ3BkS1FDQwY7AFRJIhBfY3NyZl90b2tlbgY7AEZJIjFQMmw0S2phSjl0M3NqTzI1dTdtKzQzbFFzdjVmMktjZUc1ZVNFMk9XU1BrPQY7AEY%3D--218a0a0cebae06e6b014d18d21e247a891ca28a4'

META:
REMOTE_ADDR = '::1'
SERVER_PORT = '8080'
QUERY_STRING = ''
USER_IS_ADMIN = '0'
APPENGINE_RUNTIME = 'python27'
wsgi.errors = <google.appengine.api.logservice.logservice._LogsStreamBuffer object at 0x105b5c790>
HTTP_CONTENT_LENGTH = '83'
PATH_INFO = u'/registration/'
HTTP_REFERER = 'http://localhost:8080/'
AUTH_DOMAIN = 'gmail.com'
TZ = 'UTC'
CURRENT_VERSION_ID = '1.801706933843596328'
INSTANCE_ID = 'd9ac8faff8dfc88cbfd6afedd0c9b97dbcbe'
CONTENT_LENGTH = '83'
REQUEST_ID_HASH = '4F1521C4'
HTTP_ACCEPT_LANGUAGE = 'en-US,en;q=0.8'
SERVER_PROTOCOL = 'HTTP/1.1'
HTTP_HOST = 'localhost:8080'
wsgi.multithread = True
USER_ORGANIZATION = ''
SCRIPT_NAME = u''
USER_NICKNAME = ''
SERVER_SOFTWARE = 'Development/2.0'
DJANGO_SETTINGS_MODULE = 'tradex_plus.settings'
HTTP_CONTENT_TYPE = 'application/x-www-form-urlencoded'
DATACENTER = 'us1'
HTTP_ORIGIN = 'http://localhost:8080'
wsgi.run_once = False
CURRENT_MODULE_ID = 'default'
DEFAULT_VERSION_HOSTNAME = 'localhost:8080'
wsgi.url_scheme = 'http'
APPLICATION_ID = 'dev~tradex-plus'
wsgi.version = 
wsgi.input = <cStringIO.StringI object at 0x105b3d2d8>
USER_EMAIL = ''
HTTP_X_REQUESTED_WITH = 'XMLHttpRequest'
HTTPS = 'off'
HTTP_X_APPENGINE_COUNTRY = 'ZZ'
CSRF_COOKIE = u'ZlrIA6elo93vmMXpxwpPG9HpJNrdBjM7'
PATH_TRANSLATED = '/Users/foodprinting/proj/tradex-plus/tradex_plus/wsgi.pyc'
HTTP_ACCEPT = 'application/json, text/javascript, */*; q=0.01'
wsgi.multiprocess = True
CONTENT_TYPE = 'application/x-www-form-urlencoded'
HTTP_COOKIE = '_tinyowl_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWYyYTY0ZmVjYjQxMmNlOWE0M2I2ZTMyYWE5OTgzZjI0BjsAVEkiEnNlc3Npb25fdG9rZW4GOwBGSSJgNzE5ckJnZ3hDaEZLTlRIdnViM0NXSmJFTFhvQUc4OTJNaWVTcTNGSmZGUlVWdG9DeDBSN1JTU2tXc0hUWTlxbUNXQ05DekNqSXZNdUw1MXBVV2xsZ3BkS1FDQwY7AFRJIhBfY3NyZl90b2tlbgY7AEZJIjFQMmw0S2phSjl0M3NqTzI1dTdtKzQzbFFzdjVmMktjZUc1ZVNFMk9XU1BrPQY7AEY%3D--218a0a0cebae06e6b014d18d21e247a891ca28a4'
REQUEST_LOG_ID = '8dfb77a9143ccd7c96b0ff19b9c94fe'
SERVER_NAME = 'localhost'
REQUEST_METHOD = 'POST'
HTTP_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36'
USER_ID = ''

Settings:
Using settings module tradex_plus.settings
FORMAT_MODULE_PATH = None
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
DECIMAL_SEPARATOR = '.'
FIRST_DAY_OF_WEEK = 0
CSRF_FAILURE_VIEW = 'django.views.csrf.csrf_failure'
SESSION_COOKIE_HTTPONLY = True
INSTALLED_APPS = 
PASSWORD_RESET_TIMEOUT_DAYS = u'********************'
DEFAULT_EXCEPTION_REPORTER_FILTER = 'django.views.debug.SafeExceptionReporterFilter'
LOGGING_CONFIG = 'django.utils.log.dictConfig'
LANGUAGE_CODE = 'en-us'
STATIC_URL = '/frontend/'
ROOT_URLCONF = 'tradex_plus.urls'
SESSION_COOKIE_DOMAIN = None
EMAIL_HOST_PASSWORD = u'********************'
INTERNAL_IPS = 
LOGGING = {'version': 1, 'filters': {'require_debug_false': {'()': 'django.utils.log.RequireDebugFalse'}}, 'disable_existing_loggers': False, 'handlers': {'mail_admins': {'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler', 'level': 'ERROR'}}, 'loggers': {'django.request': {'level': 'ERROR', 'handlers': ['mail_admins'], 'propagate': True}}}
DATABASE_ROUTERS = []
SHORT_DATE_FORMAT = 'm/d/Y'
DEFAULT_FROM_EMAIL = 'webmaster@localhost'
SESSION_COOKIE_AGE = 1209600
AUTHENTICATION_BACKENDS = 'django.contrib.auth.backends.ModelBackend'
AUTH_USER_MODEL = 'auth.User'
ABSOLUTE_URL_OVERRIDES = {}
DATETIME_FORMAT = 'N j, Y, P'
DATABASES = {}
SHORT_DATETIME_FORMAT = 'm/d/Y P'
FORCE_SCRIPT_NAME = None
FILE_CHARSET = 'utf-8'
STATICFILES_DIRS = '/Users/foodprinting/proj/tradex-plus/frontend'
TIME_INPUT_FORMATS = 
PROJECT_PATH = '/Users/foodprinting/proj/tradex-plus'
TRANSACTIONS_MANAGED = False
MANAGERS = 
DATE_FORMAT = 'N j, Y'
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
PROFANITIES_LIST = u'********************'
SESSION_FILE_PATH = None
STATIC_ROOT = ''
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440
LOGIN_REDIRECT_URL = '/accounts/profile/'
TEST_RUNNER = 'django.test.simple.DjangoTestSuiteRunner'
LANGUAGES_BIDI = 
MIDDLEWARE_CLASSES = 
SESSION_COOKIE_NAME = 'sessionid'
PASSWORD_HASHERS = u'********************'
EMAIL_HOST_USER = ''
ALLOWED_INCLUDE_ROOTS = 
CSRF_COOKIE_NAME = 'csrftoken'
FIXTURE_DIRS = 
X_FRAME_OPTIONS = 'SAMEORIGIN'
USE_ETAGS = False
DATE_INPUT_FORMATS = 
DEFAULT_CHARSET = 'utf-8'
EMAIL_PORT = 25
TIME_FORMAT = 'P'
USE_THOUSAND_SEPARATOR = False
FILE_UPLOAD_TEMP_DIR = None
LOGOUT_URL = '/accounts/logout/'
LOCALE_PATHS = 
PREPEND_WWW = False
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
DEBUG = True
MEDIA_URL = ''
BASE_DIR = '/Users/foodprinting/proj/tradex-plus'
STATICFILES_FINDERS = 'django.contrib.staticfiles.finders.FileSystemFinder'
THOUSAND_SEPARATOR = ','
FILE_UPLOAD_PERMISSIONS = None
SERVER_EMAIL = 'root@localhost'
SESSION_COOKIE_PATH = '/'
EMAIL_HOST = 'localhost'
DEFAULT_TABLESPACE = ''
TEMPLATE_DEBUG = True
LANGUAGE_COOKIE_NAME = 'django_language'
CACHE_MIDDLEWARE_KEY_PREFIX = u'********************'
COMMENTS_ALLOW_PROFANITIES = False
DATETIME_INPUT_FORMATS = 
SESSION_SAVE_EVERY_REQUEST = False
DEBUG_PROPAGATE_EXCEPTIONS = False
LOGIN_URL = '/accounts/login/'
FRONTEND = '/Users/foodprinting/proj/tradex-plus/frontend'
USE_TZ = True
EMAIL_USE_TLS = False
ADMIN_FOR = 
SITE_ID = 1
MEDIA_ROOT = ''
USE_I18N = True
USE_L10N = True
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}}
PROJECT_DIR = '/Users/foodprinting/proj/tradex-plus/tradex_plus'
CACHE_MIDDLEWARE_SECONDS = 600
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
APPEND_SLASH = True
TEMPLATE_LOADERS = 
NUMBER_GROUPING = 0
IGNORABLE_404_URLS = 
ADMINS = 
YEAR_MONTH_FORMAT = 'F Y'
TEMPLATE_CONTEXT_PROCESSORS = 
CSRF_COOKIE_DOMAIN = None
ALLOWED_HOSTS = []
CACHE_MIDDLEWARE_ALIAS = 'default'
WSGI_APPLICATION = 'tradex_plus.wsgi.application'
DEFAULT_INDEX_TABLESPACE = ''
TIME_ZONE = 'America/Chicago'
SESSION_CACHE_ALIAS = 'default'
CSRF_COOKIE_SECURE = False
FILE_UPLOAD_HANDLERS = 
EMAIL_SUBJECT_PREFIX = '[Django] '
DISALLOWED_USER_AGENTS = 
DEFAULT_CONTENT_TYPE = 'text/html'
TEMPLATE_STRING_IF_INVALID = ''
SESSION_COOKIE_SECURE = False
MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'
CSRF_COOKIE_PATH = '/'
SEND_BROKEN_LINK_EMAILS = False
TEMPLATE_DIRS = '/Users/foodprinting/proj/tradex-plus/frontend'
USE_X_FORWARDED_HOST = False
SIGNING_BACKEND = 'django.core.signing.TimestampSigner'
SETTINGS_MODULE = 'tradex_plus.settings'
LANGUAGES = 
SECRET_KEY = u'********************'
MONTH_DAY_FORMAT = 'F j'
SECURE_PROXY_SSL_HEADER = None
SESSION_ENGINE = 'django.contrib.sessions.backends.db'

You're seeing this error because you have DEBUG = True in your
Django settings file. Change that to False, and Django will
display a standard 500 page.

By default, Django stores sessions in your database (using the model django.contrib.sessions.models.Session). Though this is convenient, in some setups it’s faster to store session data elsewhere, so Django can be configured to store session data on your filesystem or in your cache.

Django 似乎将会话存储在您的数据库中,并使用其 ORM 框架。由于您使用 NDB,因此您不能依赖其 ORM 框架。基本上,你有两个选择。

  1. 将会话数据存储在别处。例如,您可以使用 cookie-based sessions
  2. 您可以使用支持 App Engine 的 Django-nonrel 和 Cloud Datastore