Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(42)

Side by Side Diff: appengine_django/__init__.py

Issue 908: [issue6] Google's Users API Integration (Closed) SVN Base: http://google-app-engine-django.googlecode.com/svn/trunk/
Patch Set: BaseModel.DoesNotExist attribute implemented, minor fixes Created 3 months, 3 weeks ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/python2.4 1 #!/usr/bin/python2.4
2 # 2 #
3 # Copyright 2008 Google Inc. 3 # Copyright 2008 Google Inc.
4 # 4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License. 6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at 7 # You may obtain a copy of the License at
8 # 8 #
9 # http://www.apache.org/licenses/LICENSE-2.0 9 # http://www.apache.org/licenses/LICENSE-2.0
10 # 10 #
11 # Unless required by applicable law or agreed to in writing, software 11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, 12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and 14 # See the License for the specific language governing permissions and
15 # limitations under the License. 15 # limitations under the License.
16 16
17 """Support for integrating a Django project with the appengine infrastructure. 17 """Support for integrating a Django project with the appengine infrastructure.
18 18
19 This works with both Django 0.96 (via much monkey patching) and Django 19 This works with both Django 0.96 (via much monkey patching) and Django
20 0.97.pre1. 20 0.97.pre1.
21 21
22 This module enables you to use the Django manage.py utility and *some* of it's 22 This module enables you to use the Django manage.py utility and *some* of it's
23 subcommands. View the help of manage.py for exact details. 23 subcommands. View the help of manage.py for exact details.
24 24
25 Additionally this module takes care of initialising the datastore (and a test 25 Additionally this module takes care of initialising the datastore (and a test
26 datastore) so that the Django test infrastructure can be used for your 26 datastore) so that the Django test infrastructure can be used for your
27 appengine project. 27 appengine project.
28 28
29 To use this module add the following two lines to your main.py and manage.py 29 To use this module add the following two lines to your main.py and manage.py
30 scripts at the end of your imports: 30 scripts at the end of your imports:
31 from appengine_django import InstallAppengineHelperForDjango 31 from appengine_django import InstallAppengineHelperForDjango
32 InstallAppengineHelperForDjango() 32 InstallAppengineHelperForDjango()
33 33
34 If you would like to use a version of Django other than that provided by the 34 If you would like to use a version of Django other than that provided by the
35 system all you need to do is include it in a directory just above this helper, 35 system all you need to do is include it in a directory just above this helper,
36 eg: 36 eg:
37 appengine_django/__init__.py - This file 37 appengine_django/__init__.py - This file
38 django/... - your private copy of Django. 38 django/... - your private copy of Django.
39 """ 39 """
40 40
41 import logging 41 import logging
42 import os 42 import os
43 import sys 43 import sys
44 44
45 45
46 DIR_PATH = os.path.abspath(os.path.dirname(__file__)) 46 DIR_PATH = os.path.abspath(os.path.dirname(__file__))
47 PARENT_DIR = os.path.dirname(DIR_PATH) 47 PARENT_DIR = os.path.dirname(DIR_PATH)
48 48
49 # Add this project to the start of sys path to enable direct imports. 49 # Add this project to the start of sys path to enable direct imports.
50 sys.path = [PARENT_DIR,] + sys.path 50 sys.path = [PARENT_DIR,] + sys.path
(...skipping 176 matching lines...) Show 10 above Show 10 below
227 def DisableModelValidation(): 227 def DisableModelValidation():
228 """Disables Django's model validation routines. 228 """Disables Django's model validation routines.
229 229
230 The model validation is primarily concerned with validating foreign key 230 The model validation is primarily concerned with validating foreign key
231 references. There is no equivalent checking code for datastore References at 231 references. There is no equivalent checking code for datastore References at
232 this time. 232 this time.
233 233
234 Validation needs to be disabled or serialization/deserialization will fail. 234 Validation needs to be disabled or serialization/deserialization will fail.
235 """ 235 """
236 # Imports must be performed in this function as they differ between versions. 236 # Imports must be performed in this function as they differ between versions.
237 if VERSION < (0, 97, None): 237 if VERSION < (0, 97, None):
238 from django.core import management 238 from django.core import management
239 management.get_validation_errors = lambda x, y=0: 0 239 management.get_validation_errors = lambda x, y=0: 0
240 else: 240 else:
241 from django.core.management import validation 241 from django.core.management import validation
242 validation.get_validation_errors = lambda x, y=0: 0 242 validation.get_validation_errors = lambda x, y=0: 0
243 logging.debug("Django SQL model validation disabled") 243 logging.debug("Django SQL model validation disabled")
244 244
245 def CleanupDjangoSettings(): 245 def CleanupDjangoSettings():
246 """Removes incompatible entries from the django settings module.""" 246 """Removes incompatible entries from the django settings module."""
247 247
248 # Ensure this module is installed as an application. 248 # Ensure this module is installed as an application.
249 apps = getattr(settings, "INSTALLED_APPS", ()) 249 apps = getattr(settings, "INSTALLED_APPS", ())
250 found = False 250 found = False
251 for app in apps: 251 for app in apps:
252 if app.endswith("appengine_django"): 252 if app.endswith("appengine_django"):
253 found = True 253 found = True
254 break 254 break
255 if not found: 255 if not found:
256 logging.warn("appengine_django module is not listed as an application!") 256 logging.warn("appengine_django module is not listed as an application!")
257 apps += ("appengine_django",) 257 apps += ("appengine_django",)
258 setattr(settings, "INSTALLED_APPS", apps) 258 setattr(settings, "INSTALLED_APPS", apps)
259 logging.info("Added 'appengine_django' as an application") 259 logging.info("Added 'appengine_django' as an application")
260 260
261 # Ensure the database backend is appropriately configured. 261 # Ensure the database backend is appropriately configured.
262 dbe = getattr(settings, "DATABASE_ENGINE", "") 262 dbe = getattr(settings, "DATABASE_ENGINE", "")
263 if dbe != "appengine": 263 if dbe != "appengine":
264 settings.DATABASE_ENGINE = "appengine" 264 settings.DATABASE_ENGINE = "appengine"
265 logging.warn("DATABASE_ENGINE is not configured as 'appengine'. " 265 logging.warn("DATABASE_ENGINE is not configured as 'appengine'. "
266 "Value overriden!") 266 "Value overriden!")
267 for var in ["NAME", "USER", "PASSWORD", "HOST", "PORT"]: 267 for var in ["NAME", "USER", "PASSWORD", "HOST", "PORT"]:
268 val = getattr(settings, "DATABASE_%s" % var, "") 268 val = getattr(settings, "DATABASE_%s" % var, "")
269 if val: 269 if val:
270 setattr(settings, "DATABASE_%s" % var, "") 270 setattr(settings, "DATABASE_%s" % var, "")
271 logging.warn("DATABASE_%s should be blank. Value overriden!") 271 logging.warn("DATABASE_%s should be blank. Value overriden!")
272 272
273 # Remove incompatible middleware modules. 273 # Remove incompatible middleware modules.
274 mw_mods = list(getattr(settings, "MIDDLEWARE_CLASSES", ())) 274 mw_mods = list(getattr(settings, "MIDDLEWARE_CLASSES", ()))
275 disallowed_middleware_mods = ( 275 disallowed_middleware_mods = (
276 'django.contrib.sessions.middleware.SessionMiddleware', 276 'django.contrib.sessions.middleware.SessionMiddleware',
277 'django.contrib.auth.middleware.AuthenticationMiddleware',
278 'django.middleware.doc.XViewMiddleware',) 277 'django.middleware.doc.XViewMiddleware',)
279 for modname in mw_mods[:]: 278 for modname in mw_mods[:]:
280 if modname in disallowed_middleware_mods: 279 if modname in disallowed_middleware_mods:
281 # Currently only the CommonMiddleware has been ported. As other base modu les 280 # Currently only the CommonMiddleware has been ported. As other base modu les
282 # are converted, remove from the disallowed_middleware_mods tuple. 281 # are converted, remove from the disallowed_middleware_mods tuple.
283 mw_mods.remove(modname) 282 mw_mods.remove(modname)
284 logging.warn("Middleware module '%s' is not compatible. Removed!" % 283 logging.warn("Middleware module '%s' is not compatible. Removed!" %
285 modname) 284 modname)
286 setattr(settings, "MIDDLEWARE_CLASSES", tuple(mw_mods)) 285 setattr(settings, "MIDDLEWARE_CLASSES", tuple(mw_mods))
287 286
288 # Remove incompatible application modules 287 # Remove incompatible application modules
289 app_mods = list(getattr(settings, "INSTALLED_APPS", ())) 288 app_mods = list(getattr(settings, "INSTALLED_APPS", ()))
289 disallowed_apps = (
290 'django.contrib.contenttypes',
291 'django.contrib.sessions',
292 'django.contrib.sites',)
290 for app in app_mods[:]: 293 for app in app_mods[:]:
291 if app.startswith("django."): 294 if app in disallowed_apps:
292 # TODO(mglb): Again this is probably overly broad. 295 # TODO(mglb): Again this is probably overly broad.
293 app_mods.remove(app) 296 app_mods.remove(app)
294 logging.warn("Application module '%s' is not compatible. Removed!" % app) 297 logging.warn("Application module '%s' is not compatible. Removed!" % app)
295 setattr(settings, "INSTALLED_APPS", tuple(app_mods)) 298 setattr(settings, "INSTALLED_APPS", tuple(app_mods))
296 299
297 # Remove incompatible context processors.
298 bad_processors = ('django.core.context_processors.auth',)
299 ctx_procs = list(getattr(settings, "TEMPLATE_CONTEXT_PROCESSORS", ()))
300 for proc in ctx_procs[:]:
301 if proc in bad_processors:
302 ctx_procs.remove(proc)
303 logging.warn("Template Context Processor '%s' is incompatible. Removed!"
304 % proc)
305 setattr(settings, "TEMPLATE_CONTEXT_PROCESSORS", tuple(ctx_procs))
306
307 300
308 def ModifyAvailableCommands(): 301 def ModifyAvailableCommands():
309 """Removes incompatible commands and installs replacements where possible.""" 302 """Removes incompatible commands and installs replacements where possible."""
310 if have_appserver: 303 if have_appserver:
311 # Commands are not used when running from an appserver. 304 # Commands are not used when running from an appserver.
312 return 305 return
313 from django.core import management 306 from django.core import management
314 if VERSION < (0, 97, None): 307 if VERSION < (0, 97, None):
315 RemoveCommands(management.DEFAULT_ACTION_MAPPING) 308 RemoveCommands(management.DEFAULT_ACTION_MAPPING)
316 from appengine_django.management.commands import runserver 309 from appengine_django.management.commands import runserver
317 management.DEFAULT_ACTION_MAPPING['runserver'] = runserver.v096_command 310 management.DEFAULT_ACTION_MAPPING['runserver'] = runserver.v096_command
318 from appengine_django.management.commands import flush 311 from appengine_django.management.commands import flush
319 management.DEFAULT_ACTION_MAPPING['flush'] = flush.v096_command 312 management.DEFAULT_ACTION_MAPPING['flush'] = flush.v096_command
320 from appengine_django.management.commands import reset 313 from appengine_django.management.commands import reset
321 management.DEFAULT_ACTION_MAPPING['reset'] = reset.v096_command 314 management.DEFAULT_ACTION_MAPPING['reset'] = reset.v096_command
322 else: 315 else:
323 management.get_commands() 316 management.get_commands()
324 RemoveCommands(management._commands) 317 RemoveCommands(management._commands)
325 # Django 0.97 will install the replacements automatically. 318 # Django 0.97 will install the replacements automatically.
326 logging.debug("Removed incompatible Django manage.py commands") 319 logging.debug("Removed incompatible Django manage.py commands")
327 320
328 321
329 def RemoveCommands(command_dict): 322 def RemoveCommands(command_dict):
330 """Removes incompatible commands from the specified command dictionary.""" 323 """Removes incompatible commands from the specified command dictionary."""
331 for cmd in command_dict.keys(): 324 for cmd in command_dict.keys():
332 if cmd.startswith("sql"): 325 if cmd.startswith("sql"):
333 del command_dict[cmd] 326 del command_dict[cmd]
334 elif cmd in INCOMPATIBLE_COMMANDS: 327 elif cmd in INCOMPATIBLE_COMMANDS:
335 del command_dict[cmd] 328 del command_dict[cmd]
336 329
337 330
338 def InstallReplacementImpModule(): 331 def InstallReplacementImpModule():
339 """Install a replacement for the imp module removed by the appserver. 332 """Install a replacement for the imp module removed by the appserver.
340 333
341 This is only required for Django 0.97 which uses imp.find_module to find 334 This is only required for Django 0.97 which uses imp.find_module to find
342 mangement modules provided by applications. 335 mangement modules provided by applications.
343 """ 336 """
344 if VERSION < (0, 97, None) or not have_appserver: 337 if VERSION < (0, 97, None) or not have_appserver:
345 return 338 return
346 modname = 'appengine_django.replacement_imp' 339 modname = 'appengine_django.replacement_imp'
347 imp_mod = __import__(modname, {}, [], ['']) 340 imp_mod = __import__(modname, {}, [], [''])
348 sys.modules['imp'] = imp_mod 341 sys.modules['imp'] = imp_mod
349 logging.debug("Installed replacement imp module") 342 logging.debug("Installed replacement imp module")
350 343
351 344
352 def InstallAppengineHelperForDjango(): 345 def InstallAppengineHelperForDjango():
353 """Installs and Patches all of the classes/methods required for integration. 346 """Installs and Patches all of the classes/methods required for integration.
354 347
355 If the variable DEBUG_APPENGINE_DJANGO is set in the environment verbose 348 If the variable DEBUG_APPENGINE_DJANGO is set in the environment verbose
356 logging of the actions taken will be enabled. 349 logging of the actions taken will be enabled.
357 """ 350 """
358 if os.getenv("DEBUG_APPENGINE_DJANGO"): 351 if os.getenv("DEBUG_APPENGINE_DJANGO"):
359 logging.getLogger().setLevel(logging.DEBUG) 352 logging.getLogger().setLevel(logging.DEBUG)
360 else: 353 else:
361 logging.getLogger().setLevel(logging.INFO) 354 logging.getLogger().setLevel(logging.INFO)
362 logging.debug("Loading the Google App Engine Helper for Django...") 355 logging.debug("Loading the Google App Engine Helper for Django...")
363 356
364 # Force Django to reload its settings. 357 # Force Django to reload its settings.
365 settings._target = None 358 settings._target = None
366 359
367 # Must set this env var *before* importing any more of Django. 360 # Must set this env var *before* importing any more of Django.
368 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' 361 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
369 362
370 LoadAppengineEnvironment() 363 LoadAppengineEnvironment()
371 InstallReplacementImpModule() 364 InstallReplacementImpModule()
372 InstallAppengineDatabaseBackend() 365 InstallAppengineDatabaseBackend()
373 PatchDjangoSerializationModules() 366 PatchDjangoSerializationModules()
374 CleanupDjangoSettings() 367 CleanupDjangoSettings()
375 ModifyAvailableCommands() 368 ModifyAvailableCommands()
376 InstallGoogleSMTPConnection() 369 InstallGoogleSMTPConnection()
370 InstallAuthentication()
377 371
378 logging.debug("Successfully loaded the Google App Engine Helper for Django.") 372 logging.debug("Successfully loaded the Google App Engine Helper for Django.")
379 373
380 374
381 def InstallGoogleSMTPConnection(): 375 def InstallGoogleSMTPConnection():
382 from appengine_django import mail as gmail 376 from appengine_django import mail as gmail
383 from django.core import mail 377 from django.core import mail
384 if VERSION >= (0, 97, None): 378 if VERSION >= (0, 97, None):
385 logging.debug("Installing Google Email Adapter for Django 0.97+") 379 logging.debug("Installing Google Email Adapter for Django 0.97+")
386 mail.SMTPConnection = gmail.GoogleSMTPConnection 380 mail.SMTPConnection = gmail.GoogleSMTPConnection
387 else: 381 else:
388 logging.debug("Installing Google Email Adapter for Django 0.96") 382 logging.debug("Installing Google Email Adapter for Django 0.96")
389 mail.send_mass_mail = gmail.send_mass_mail 383 mail.send_mass_mail = gmail.send_mass_mail
390 mail.mail_admins = gmail.mail_admins 384 mail.mail_admins = gmail.mail_admins
391 mail.mail_managers = gmail.mail_managers 385 mail.mail_managers = gmail.mail_managers
386
387 def InstallAuthentication():
388 logging.debug("Installing authentication framework")
389 from django.contrib.auth import models as django_models
390 from appengine_django.auth.models import DjangoUser
391 django_models.User = DjangoUser
392 from django.contrib.auth import middleware as django_middleware
393 from appengine_django.auth import middleware
394 django_middleware.AuthenticationMiddleware = middleware.AuthenticationMiddlewa re
OLDNEW

Powered by Google App Engine
This is Rietveld r305