summaryrefslogtreecommitdiff
path: root/django/core
diff options
context:
space:
mode:
authorChristopher Long <indirecthit@gmail.com>2006-08-14 18:52:03 +0000
committerChristopher Long <indirecthit@gmail.com>2006-08-14 18:52:03 +0000
commit4cfd3203a67cd6e1fccccab5c85da5551814d2ee (patch)
tree0b8ed10b392cdf17b218aab3a0856f2ba58160ad /django/core
parent4f0118995c43fd3cb5f79ffcbaf10b1115d8e434 (diff)
[per-object-permissions] Merged to revision 3582
git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@3583 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/core')
-rw-r--r--django/core/management.py60
-rw-r--r--django/core/serializers/json.py6
-rw-r--r--django/core/servers/basehttp.py4
-rw-r--r--django/core/urlresolvers.py60
4 files changed, 84 insertions, 46 deletions
diff --git a/django/core/management.py b/django/core/management.py
index 14182cbdff..a469c72901 100644
--- a/django/core/management.py
+++ b/django/core/management.py
@@ -94,12 +94,15 @@ def get_sql_create(app):
"Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n"))
sys.exit(1)
- # Get installed models, so we generate REFERENCES right
+ # Get installed models, so we generate REFERENCES right.
+ # We trim models from the current app so that the sqlreset command does not
+ # generate invalid SQL (leaving models out of known_models is harmless, so
+ # we can be conservative).
+ app_models = models.get_models(app)
final_output = []
- known_models = set(_get_installed_models(_get_table_list()))
+ known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models])
pending_references = {}
- app_models = models.get_models(app)
for model in app_models:
output, references = _get_sql_model_create(model, known_models)
@@ -118,10 +121,13 @@ def get_sql_create(app):
# but don't exist physically
not_installed_models = set(pending_references.keys())
if not_installed_models:
- final_output.append('-- The following references should be added but depend on non-existant tables:')
+ alter_sql = []
for model in not_installed_models:
- final_output.extend(['-- ' + sql for sql in
+ alter_sql.extend(['-- ' + sql for sql in
_get_sql_for_pending_references(model, pending_references)])
+ if alter_sql:
+ final_output.append('-- The following references should be added but depend on non-existent tables:')
+ final_output.extend(alter_sql)
return final_output
get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app name(s)."
@@ -192,7 +198,6 @@ def _get_sql_for_pending_references(model, pending_references):
data_types = get_creation_module().DATA_TYPES
final_output = []
- reference_names = {}
if backend.supports_constraints:
opts = model._meta
if model in pending_references:
@@ -202,12 +207,9 @@ def _get_sql_for_pending_references(model, pending_references):
r_col = f.column
table = opts.db_table
col = opts.get_field(f.rel.field_name).column
- r_name = '%s_referencing_%s_%s' % (r_col, table, col)
- if r_name in reference_names:
- reference_names[r_name] += 1
- r_name += '_%s' % reference_names[r_name]
- else:
- reference_names[r_name] = 0
+ # For MySQL, r_name must be unique in the first 64 characters.
+ # So we are careful with character usage here.
+ r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
(backend.quote_name(r_table), r_name,
backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col)))
@@ -299,7 +301,7 @@ def get_sql_delete(app):
(style.SQL_KEYWORD('ALTER TABLE'),
style.SQL_TABLE(backend.quote_name(table)),
style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
- style.SQL_FIELD(backend.quote_name("%s_referencing_%s_%s" % (col, r_table, r_col)))))
+ style.SQL_FIELD(backend.quote_name('%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table))))))))
del references_to_delete[model]
# Output DROP TABLE statements for many-to-many tables.
@@ -696,9 +698,7 @@ def inspectdb():
introspection_module = get_introspection_module()
- def table2model(table_name):
- object_name = table_name.title().replace('_', '')
- return object_name.endswith('s') and object_name[:-1] or object_name
+ table2model = lambda table_name: table_name.title().replace('_', '')
cursor = connection.cursor()
yield "# This is an auto-generated Django model module."
@@ -727,6 +727,10 @@ def inspectdb():
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
extra_params = {} # Holds Field parameters such as 'db_column'.
+ if ' ' in att_name:
+ extra_params['db_column'] = att_name
+ att_name = att_name.replace(' ', '')
+ comment_notes.append('Field renamed to remove spaces.')
if keyword.iskeyword(att_name):
extra_params['db_column'] = att_name
att_name += '_field'
@@ -957,6 +961,12 @@ def get_validation_errors(outfile, app=None):
f = opts.get_field(fn)
except models.FieldDoesNotExist:
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
+ # date_hierarchy
+ if opts.admin.date_hierarchy:
+ try:
+ f = opts.get_field(opts.admin.date_hierarchy)
+ except models.FieldDoesNotExist:
+ e.add(opts, '"admin.date_hierarchy" refers to %r, which isn\'t a field.' % opts.admin.date_hierarchy)
# Check ordering attribute.
if opts.ordering:
@@ -1132,7 +1142,14 @@ def dbshell():
dbshell.args = ""
def runfcgi(args):
- """Run this project as a FastCGI application. requires flup."""
+ "Runs this project as a FastCGI application. Requires flup."
+ from django.conf import settings
+ from django.utils import translation
+ # Activate the current language, because it won't get activated later.
+ try:
+ translation.activate(settings.LANGUAGE_CODE)
+ except AttributeError:
+ pass
from django.core.servers.fastcgi import runfastcgi
runfastcgi(args)
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
@@ -1289,7 +1306,11 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
if action not in NO_SQL_TRANSACTION:
print style.SQL_KEYWORD("COMMIT;")
-def execute_manager(settings_mod, argv=None):
+def setup_environ(settings_mod):
+ """
+ Configure the runtime environment. This can also be used by external
+ scripts wanting to set up a similar environment to manage.py.
+ """
# Add this project to sys.path so that it's importable in the conventional
# way. For example, if this file (manage.py) lives in a directory
# "myproject", this code would add "/path/to/myproject" to sys.path.
@@ -1301,7 +1322,10 @@ def execute_manager(settings_mod, argv=None):
# Set DJANGO_SETTINGS_MODULE appropriately.
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
+ return project_directory
+def execute_manager(settings_mod, argv=None):
+ project_directory = setup_environ(settings_mod)
action_mapping = DEFAULT_ACTION_MAPPING.copy()
# Remove the "startproject" command from the action_mapping, because that's
diff --git a/django/core/serializers/json.py b/django/core/serializers/json.py
index dd6513db57..a8b4259099 100644
--- a/django/core/serializers/json.py
+++ b/django/core/serializers/json.py
@@ -41,11 +41,11 @@ class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
TIME_FORMAT = "%H:%M:%S"
def default(self, o):
- if isinstance(o, datetime.date):
+ if isinstance(o, datetime.datetime):
+ return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
+ elif isinstance(o, datetime.date):
return o.strftime(self.DATE_FORMAT)
elif isinstance(o, datetime.time):
return o.strftime(self.TIME_FORMAT)
- elif isinstance(o, datetime.datetime):
- return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
else:
return super(self, DateTimeAwareJSONEncoder).default(o) \ No newline at end of file
diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py
index 7ce5706c23..4bd0e50e53 100644
--- a/django/core/servers/basehttp.py
+++ b/django/core/servers/basehttp.py
@@ -547,10 +547,6 @@ class WSGIRequestHandler(BaseHTTPRequestHandler):
env['PATH_INFO'] = urllib.unquote(path)
env['QUERY_STRING'] = query
-
- host = self.address_string()
- if host != self.client_address[0]:
- env['REMOTE_HOST'] = host
env['REMOTE_ADDR'] = self.client_address[0]
if self.headers.typeheader is None:
diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index 83fffacefb..2f557b90a6 100644
--- a/django/core/urlresolvers.py
+++ b/django/core/urlresolvers.py
@@ -86,10 +86,15 @@ class MatchChecker(object):
class RegexURLPattern(object):
def __init__(self, regex, callback, default_args=None):
# regex is a string representing a regular expression.
- # callback is something like 'foo.views.news.stories.story_detail',
- # which represents the path to a module and a view function name.
+ # callback is either a string like 'foo.views.news.stories.story_detail'
+ # which represents the path to a module and a view function name, or a
+ # callable object (view).
self.regex = re.compile(regex)
- self.callback = callback
+ if callable(callback):
+ self._callback = callback
+ else:
+ self._callback = None
+ self._callback_str = callback
self.default_args = default_args or {}
def resolve(self, path):
@@ -106,23 +111,28 @@ class RegexURLPattern(object):
# In both cases, pass any extra_kwargs as **kwargs.
kwargs.update(self.default_args)
- try: # Lazily load self.func.
- return self.func, args, kwargs
- except AttributeError:
- self.func = self.get_callback()
- return self.func, args, kwargs
+ return self.callback, args, kwargs
- def get_callback(self):
- mod_name, func_name = get_mod_func(self.callback)
+ def _get_callback(self):
+ if self._callback is not None:
+ return self._callback
+ mod_name, func_name = get_mod_func(self._callback_str)
try:
- return getattr(__import__(mod_name, '', '', ['']), func_name)
+ self._callback = getattr(__import__(mod_name, '', '', ['']), func_name)
except ImportError, e:
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
except AttributeError, e:
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
+ return self._callback
+ callback = property(_get_callback)
def reverse(self, viewname, *args, **kwargs):
- if viewname != self.callback:
+ mod_name, func_name = get_mod_func(viewname)
+ try:
+ lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
+ except (ImportError, AttributeError):
+ raise NoReverseMatch
+ if lookup_view != self.callback:
raise NoReverseMatch
return self.reverse_helper(*args, **kwargs)
@@ -130,12 +140,13 @@ class RegexURLPattern(object):
return reverse_helper(self.regex, *args, **kwargs)
class RegexURLResolver(object):
- def __init__(self, regex, urlconf_name):
+ def __init__(self, regex, urlconf_name, default_kwargs=None):
# regex is a string representing a regular expression.
# urlconf_name is a string representing the module containing urlconfs.
self.regex = re.compile(regex)
self.urlconf_name = urlconf_name
self.callback = None
+ self.default_kwargs = default_kwargs or {}
def resolve(self, path):
tried = []
@@ -149,7 +160,8 @@ class RegexURLResolver(object):
tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
else:
if sub_match:
- return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match[2])
+ sub_match_dict = dict(self.default_kwargs, **sub_match[2])
+ return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match_dict)
tried.append(pattern.regex.pattern)
raise Resolver404, {'tried': tried, 'path': new_path}
@@ -183,22 +195,28 @@ class RegexURLResolver(object):
def resolve500(self):
return self._resolve_special('500')
- def reverse(self, viewname, *args, **kwargs):
+ def reverse(self, lookup_view, *args, **kwargs):
+ if not callable(lookup_view):
+ mod_name, func_name = get_mod_func(lookup_view)
+ try:
+ lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
+ except (ImportError, AttributeError):
+ raise NoReverseMatch
for pattern in self.urlconf_module.urlpatterns:
if isinstance(pattern, RegexURLResolver):
try:
- return pattern.reverse_helper(viewname, *args, **kwargs)
+ return pattern.reverse_helper(lookup_view, *args, **kwargs)
except NoReverseMatch:
continue
- elif pattern.callback == viewname:
+ elif pattern.callback == lookup_view:
try:
return pattern.reverse_helper(*args, **kwargs)
except NoReverseMatch:
continue
raise NoReverseMatch
- def reverse_helper(self, viewname, *args, **kwargs):
- sub_match = self.reverse(viewname, *args, **kwargs)
+ def reverse_helper(self, lookup_view, *args, **kwargs):
+ sub_match = self.reverse(lookup_view, *args, **kwargs)
result = reverse_helper(self.regex, *args, **kwargs)
return result + sub_match
@@ -209,11 +227,11 @@ def resolve(path, urlconf=None):
resolver = RegexURLResolver(r'^/', urlconf)
return resolver.resolve(path)
-def reverse(viewname, urlconf, args=None, kwargs=None):
+def reverse(viewname, urlconf=None, args=None, kwargs=None):
args = args or []
kwargs = kwargs or {}
if urlconf is None:
from django.conf import settings
urlconf = settings.ROOT_URLCONF
resolver = RegexURLResolver(r'^/', urlconf)
- return resolver.reverse(viewname, *args, **kwargs)
+ return '/' + resolver.reverse(viewname, *args, **kwargs)