diff options
| author | Robin Munn <robin.munn@gmail.com> | 2006-10-24 07:49:37 +0000 |
|---|---|---|
| committer | Robin Munn <robin.munn@gmail.com> | 2006-10-24 07:49:37 +0000 |
| commit | 0b059aa4eadc1d95ceca3a32821b65a9fb2a53e8 (patch) | |
| tree | 76f84c62e3ac5cd5172d43dd73a651bb8574e2d1 /django/core | |
| parent | 1bb4fa2cb66269b1eff3b7d73f8c7864c0622368 (diff) | |
sqlalchemy: Merged revisions 3832 to 3917 from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/sqlalchemy@3918 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/core')
| -rw-r--r-- | django/core/handlers/base.py | 35 | ||||
| -rw-r--r-- | django/core/handlers/modpython.py | 37 | ||||
| -rw-r--r-- | django/core/handlers/wsgi.py | 8 | ||||
| -rw-r--r-- | django/core/management.py | 114 | ||||
| -rw-r--r-- | django/core/servers/basehttp.py | 2 | ||||
| -rw-r--r-- | django/core/urlresolvers.py | 3 | ||||
| -rw-r--r-- | django/core/validators.py | 4 |
7 files changed, 110 insertions, 93 deletions
diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py index 62217acdce..213c528952 100644 --- a/django/core/handlers/base.py +++ b/django/core/handlers/base.py @@ -48,7 +48,7 @@ class BaseHandler(object): if hasattr(mw_instance, 'process_exception'): self._exception_middleware.insert(0, mw_instance.process_exception) - def get_response(self, path, request): + def get_response(self, request): "Returns an HttpResponse object for the given HttpRequest" from django.core import exceptions, urlresolvers from django.core.mail import mail_admins @@ -62,7 +62,7 @@ class BaseHandler(object): resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF) try: - callback, callback_args, callback_kwargs = resolver.resolve(path) + callback, callback_args, callback_kwargs = resolver.resolve(request.path) # Apply view middleware for middleware_method in self._view_middleware: @@ -89,7 +89,8 @@ class BaseHandler(object): return response except http.Http404, e: if settings.DEBUG: - return self.get_technical_error_response(request, is404=True, exception=e) + from django.views import debug + return debug.technical_404_response(request, e) else: callback, param_dict = resolver.resolve404() return callback(request, **param_dict) @@ -99,39 +100,23 @@ class BaseHandler(object): pass # See http://code.djangoproject.com/ticket/1023 except: # Handle everything else, including SuspiciousOperation, etc. if settings.DEBUG: - return self.get_technical_error_response(request) + from django.views import debug + return debug.technical_500_response(request, *sys.exc_info()) else: # Get the exception info now, in case another exception is thrown later. exc_info = sys.exc_info() receivers = dispatcher.send(signal=signals.got_request_exception) # When DEBUG is False, send an error message to the admins. - subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', '')) + subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path) try: request_repr = repr(request) except: request_repr = "Request repr() unavailable" message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr) mail_admins(subject, message, fail_silently=True) - return self.get_friendly_error_response(request, resolver) - - def get_friendly_error_response(self, request, resolver): - """ - Returns an HttpResponse that displays a PUBLIC error message for a - fundamental error. - """ - callback, param_dict = resolver.resolve500() - return callback(request, **param_dict) - - def get_technical_error_response(self, request, is404=False, exception=None): - """ - Returns an HttpResponse that displays a TECHNICAL error message for a - fundamental error. - """ - from django.views import debug - if is404: - return debug.technical_404_response(request, exception) - else: - return debug.technical_500_response(request, *sys.exc_info()) + # Return an HttpResponse that displays a friendly error message. + callback, param_dict = resolver.resolve500() + return callback(request, **param_dict) def _get_traceback(self, exc_info=None): "Helper function to return the traceback as a string" diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py index 41d9a578c5..bf759db068 100644 --- a/django/core/handlers/modpython.py +++ b/django/core/handlers/modpython.py @@ -102,7 +102,7 @@ class ModPythonRequest(http.HttpRequest): 'REQUEST_METHOD': self._req.method, 'SCRIPT_NAME': None, # Not supported 'SERVER_NAME': self._req.server.server_hostname, - 'SERVER_PORT': self._req.server.port, + 'SERVER_PORT': str(self._req.connection.local_addr[1]), 'SERVER_PROTOCOL': self._req.protocol, 'SERVER_SOFTWARE': 'mod_python' } @@ -139,10 +139,6 @@ class ModPythonHandler(BaseHandler): # that use settings now can work from django.conf import settings - if settings.ENABLE_PSYCO: - import psyco - psyco.profile() - # if we need to set up middleware, now that settings works we can do it now. if self._request_middleware is None: self.load_middleware() @@ -150,7 +146,7 @@ class ModPythonHandler(BaseHandler): dispatcher.send(signal=signals.request_started) try: request = ModPythonRequest(req) - response = self.get_response(req.uri, request) + response = self.get_response(request) # Apply response middleware for middleware_method in self._response_middleware: @@ -160,23 +156,20 @@ class ModPythonHandler(BaseHandler): dispatcher.send(signal=signals.request_finished) # Convert our custom HttpResponse object back into the mod_python req. - populate_apache_request(response, req) - return 0 # mod_python.apache.OK + req.content_type = response['Content-Type'] + for key, value in response.headers.items(): + if key != 'Content-Type': + req.headers_out[key] = value + for c in response.cookies.values(): + req.headers_out.add('Set-Cookie', c.output(header='')) + req.status = response.status_code + try: + for chunk in response: + req.write(chunk) + finally: + response.close() -def populate_apache_request(http_response, mod_python_req): - "Populates the mod_python request object with an HttpResponse" - mod_python_req.content_type = http_response['Content-Type'] - for key, value in http_response.headers.items(): - if key != 'Content-Type': - mod_python_req.headers_out[key] = value - for c in http_response.cookies.values(): - mod_python_req.headers_out.add('Set-Cookie', c.output(header='')) - mod_python_req.status = http_response.status_code - try: - for chunk in http_response: - mod_python_req.write(chunk) - finally: - http_response.close() + return 0 # mod_python.apache.OK def handler(req): # mod_python hooks into this function. diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py index 85e234c8d2..2998bd31f6 100644 --- a/django/core/handlers/wsgi.py +++ b/django/core/handlers/wsgi.py @@ -74,7 +74,7 @@ class WSGIRequest(http.HttpRequest): def __init__(self, environ): self.environ = environ self.path = environ['PATH_INFO'] - self.META = environ + self.META = environ self.method = environ['REQUEST_METHOD'].upper() def __repr__(self): @@ -174,10 +174,6 @@ class WSGIHandler(BaseHandler): def __call__(self, environ, start_response): from django.conf import settings - if settings.ENABLE_PSYCO: - import psyco - psyco.profile() - # Set up middleware if needed. We couldn't do this earlier, because # settings weren't available. if self._request_middleware is None: @@ -186,7 +182,7 @@ class WSGIHandler(BaseHandler): dispatcher.send(signal=signals.request_started) try: request = WSGIRequest(environ) - response = self.get_response(request.path, request) + response = self.get_response(request) # Apply response middleware for middleware_method in self._response_middleware: diff --git a/django/core/management.py b/django/core/management.py index 87e5053791..5e709db6ac 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -103,7 +103,6 @@ def get_sql_create(app): known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models]) pending_references = {} - for model in app_models: output, references = _get_sql_model_create(model, known_models) final_output.extend(output) @@ -147,7 +146,7 @@ def _get_sql_model_create(model, known_models=set()): table_output = [] pending_references = {} for f in opts.fields: - if isinstance(f, models.ForeignKey): + if isinstance(f, (models.ForeignKey, models.OneToOneField)): rel_field = f.rel.get_related_field() data_type = get_rel_data_type(rel_field) else: @@ -398,32 +397,39 @@ get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting Postg get_sql_sequence_reset.args = APP_ARGS def get_sql_indexes(app): - "Returns a list of the CREATE INDEX SQL statements for the given app." - from django.db import backend, models + "Returns a list of the CREATE INDEX SQL statements for all models in the given app." + from django.db import models output = [] - for model in models.get_models(app): - for f in model._meta.fields: - if f.db_index: - unique = f.unique and 'UNIQUE ' or '' - output.append( - style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \ - style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \ - style.SQL_KEYWORD('ON') + ' ' + \ - style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \ - "(%s);" % style.SQL_FIELD(backend.quote_name(f.column)) - ) + output.extend(get_sql_indexes_for_model(model)) return output get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)." get_sql_indexes.args = APP_ARGS +def get_sql_indexes_for_model(model): + "Returns the CREATE INDEX SQL statements for a single model" + from django.db import backend + output = [] + + for f in model._meta.fields: + if f.db_index: + unique = f.unique and 'UNIQUE ' or '' + output.append( + style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \ + style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \ + style.SQL_KEYWORD('ON') + ' ' + \ + style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \ + "(%s);" % style.SQL_FIELD(backend.quote_name(f.column)) + ) + return output + def get_sql_all(app): "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module." return get_sql_create(app) + get_sql_initial_data(app) + get_sql_indexes(app) get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)." get_sql_all.args = APP_ARGS -def syncdb(verbosity=2, interactive=True): +def syncdb(verbosity=1, interactive=True): "Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." from django.db import connection, transaction, models, get_creation_module from django.db.models import signals @@ -457,21 +463,21 @@ def syncdb(verbosity=2, interactive=True): pending_references = {} for app in models.get_apps(): + app_name = app.__name__.split('.')[-2] model_list = models.get_models(app) for model in model_list: # Create the model's database table, if it doesn't already exist. + if verbosity >= 2: + print "Processing %s.%s model" % (app_name, model._meta.object_name) if model._meta.db_table in table_list: continue sql, references = _get_sql_model_create(model, seen_models) seen_models.add(model) created_models.add(model) for refto, refs in references.items(): - try: - pending_references[refto].extend(refs) - except KeyError: - pending_references[refto] = refs + pending_references.setdefault(refto, []).extend(refs) sql.extend(_get_sql_for_pending_references(model, pending_references)) - if verbosity >= 2: + if verbosity >= 1: print "Creating table %s" % model._meta.db_table for statement in sql: cursor.execute(statement) @@ -482,7 +488,7 @@ def syncdb(verbosity=2, interactive=True): sql = _get_many_to_many_sql_for_model(model) if sql: if verbosity >= 2: - print "Creating many-to-many tables for %s model" % model.__name__ + print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name) for statement in sql: cursor.execute(statement) @@ -491,6 +497,9 @@ def syncdb(verbosity=2, interactive=True): # Send the post_syncdb signal, so individual apps can do whatever they need # to do at this point. for app in models.get_apps(): + app_name = app.__name__.split('.')[-2] + if verbosity >= 2: + print "Running post-sync handlers for application", app_name dispatcher.send(signal=signals.post_syncdb, sender=app, app=app, created_models=created_models, verbosity=verbosity, interactive=interactive) @@ -501,18 +510,37 @@ def syncdb(verbosity=2, interactive=True): if model in created_models: initial_sql = get_sql_initial_data_for_model(model) if initial_sql: - if verbosity >= 2: - print "Installing initial data for %s model" % model._meta.object_name + if verbosity >= 1: + print "Installing initial data for %s.%s model" % (app_name, model._meta.object_name) try: for sql in initial_sql: cursor.execute(sql) except Exception, e: - sys.stderr.write("Failed to install initial SQL data for %s model: %s" % \ - (model._meta.object_name, e)) + sys.stderr.write("Failed to install initial SQL data for %s.%s model: %s" % \ + (app_name, model._meta.object_name, e)) transaction.rollback_unless_managed() else: transaction.commit_unless_managed() + # Install SQL indicies for all newly created models + for app in models.get_apps(): + app_name = app.__name__.split('.')[-2] + for model in models.get_models(app): + if model in created_models: + index_sql = get_sql_indexes_for_model(model) + if index_sql: + if verbosity >= 1: + print "Installing index for %s.%s model" % (app_name, model._meta.object_name) + try: + for sql in index_sql: + cursor.execute(sql) + except Exception, e: + sys.stderr.write("Failed to install index for %s.%s model: %s" % \ + (app_name, model._meta.object_name, e)) + transaction.rollback_unless_managed() + else: + transaction.commit_unless_managed() + syncdb.args = '' def get_admin_index(app): @@ -596,7 +624,7 @@ The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n') install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database." install.args = APP_ARGS -def reset(app): +def reset(app, interactive=True): "Executes the equivalent of 'get_sql_reset' in the current database." from django.db import connection, transaction app_name = app.__name__.split('.')[-2] @@ -607,21 +635,25 @@ def reset(app): _check_for_validation_errors(app) sql_list = get_sql_reset(app) - confirm = raw_input(""" + if interactive: + confirm = raw_input(""" You have requested a database reset. This will IRREVERSIBLY DESTROY any data in your database. Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: """) + else: + confirm = 'yes' + if confirm == 'yes': try: cursor = connection.cursor() for sql in sql_list: cursor.execute(sql) except Exception, e: - sys.stderr.write(style.ERROR("""Error: %s couldn't be installed. Possible reasons: + sys.stderr.write(style.ERROR("""Error: %s couldn't be reset. Possible reasons: * The database isn't running or isn't configured correctly. - * At least one of the database tables already exists. + * At least one of the database tables doesn't exist. * The SQL was invalid. Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run. The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n') @@ -820,7 +852,8 @@ def get_validation_errors(outfile, app=None): validates all models of all installed apps. Writes errors, if any, to outfile. Returns number of errors. """ - from django.db import models + from django.conf import settings + from django.db import models, connection from django.db.models.loading import get_app_errors from django.db.models.fields.related import RelatedObject @@ -862,6 +895,12 @@ def get_validation_errors(outfile, app=None): if f.db_index not in (None, True, False): e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name) + # Check that maxlength <= 255 if using older MySQL versions. + if settings.DATABASE_ENGINE == 'mysql': + db_version = connection.get_server_version() + if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255: + e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]]))) + # Check to see if the related field will clash with any # existing fields, m2m fields, m2m related objects or related objects if f.rel: @@ -1169,7 +1208,7 @@ def runfcgi(args): runfastcgi(args) runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]' -def test(verbosity, app_labels): +def test(app_labels, verbosity=1): "Runs the test suite for the specified applications" from django.conf import settings from django.db.models import get_app, get_apps @@ -1271,10 +1310,10 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None): help='Tells Django to NOT prompt the user for input of any kind.') parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True, help='Tells Django to NOT use the auto-reloader when running the development server.') - parser.add_option('--verbosity', action='store', dest='verbosity', default='2', + parser.add_option('--verbosity', action='store', dest='verbosity', default='1', type='choice', choices=['0', '1', '2'], help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), - parser.add_option('--adminmedia', dest='admin_media_path', default='', help='Lets you manually specify the directory to serve admin media from when running the development server.'), + parser.add_option('--adminmedia', dest='admin_media_path', default='', help='Specifies the directory from which to serve admin media for runserver.'), options, args = parser.parse_args(argv[1:]) @@ -1320,7 +1359,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None): parser.print_usage_and_exit() elif action == 'test': try: - action_mapping[action](int(options.verbosity), args[1:]) + action_mapping[action](args[1:], int(options.verbosity)) except IndexError: parser.print_usage_and_exit() elif action in ('startapp', 'startproject'): @@ -1354,7 +1393,10 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None): if action not in NO_SQL_TRANSACTION: print style.SQL_KEYWORD("BEGIN;") for mod in mod_list: - output = action_mapping[action](mod) + if action == 'reset': + output = action_mapping[action](mod, options.interactive) + else: + output = action_mapping[action](mod) if output: print '\n'.join(output) if action not in NO_SQL_TRANSACTION: diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index fe534d5da0..a16b8b675a 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -594,7 +594,7 @@ class AdminMediaHandler(object): Use this ONLY LOCALLY, for development! This hasn't been tested for security and is not super efficient. """ - def __init__(self, application, media_dir = None): + def __init__(self, application, media_dir=None): from django.conf import settings self.application = application if not media_dir: diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index 2f557b90a6..45705cb223 100644 --- a/django/core/urlresolvers.py +++ b/django/core/urlresolvers.py @@ -15,7 +15,8 @@ class Resolver404(Http404): pass class NoReverseMatch(Exception): - pass + # Don't make this raise an error when used in a template. + silent_variable_failure = True def get_mod_func(callback): # Converts 'django.views.news.stories.story_detail' to diff --git a/django/core/validators.py b/django/core/validators.py index f2f3f44914..4c3f59143e 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -249,7 +249,7 @@ def hasNoProfanities(field_data, all_data): Watch your mouth! The words "f--k" and "s--t" are not allowed here. """ field_data = field_data.lower() # normalize - words_seen = [w for w in settings.PROFANITIES_LIST if field_data.find(w) > -1] + words_seen = [w for w in settings.PROFANITIES_LIST if w in field_data] if words_seen: from django.utils.text import get_text_list plural = len(words_seen) > 1 @@ -377,7 +377,7 @@ class IsValidFloat(object): if len(data) > max_allowed_length: raise ValidationError, ngettext("Please enter a valid decimal number with at most %s total digit.", "Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits - if (not '.' in data and len(data) > (max_allowed_length - self.decimal_places)) or ('.' in data and len(data) > (self.max_digits - (self.decimal_places - len(data.split('.')[1])) + 1)): + if (not '.' in data and len(data) > (max_allowed_length - self.decimal_places - 1)) or ('.' in data and len(data) > (max_allowed_length - (self.decimal_places - len(data.split('.')[1])))): raise ValidationError, ngettext( "Please enter a valid decimal number with a whole part of at most %s digit.", "Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places) if '.' in data and len(data.split('.')[1]) > self.decimal_places: |
