Added 'django-admin.py validate', which validates all installed models. Validation only handles common errors at this point, but we'll be improving it each time we think of a potential model syntax problem. Also changed the development Web server to validate automatically at server start.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@503 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4a7159865e
commit
8f9e5b6b3b
|
@ -7,7 +7,9 @@ ACTION_MAPPING = {
|
||||||
'adminindex': management.get_admin_index,
|
'adminindex': management.get_admin_index,
|
||||||
'createsuperuser': management.createsuperuser,
|
'createsuperuser': management.createsuperuser,
|
||||||
# 'dbcheck': management.database_check,
|
# 'dbcheck': management.database_check,
|
||||||
|
'init': management.init,
|
||||||
'inspectdb': management.inspectdb,
|
'inspectdb': management.inspectdb,
|
||||||
|
'install': management.install,
|
||||||
'runserver': management.runserver,
|
'runserver': management.runserver,
|
||||||
'sql': management.get_sql_create,
|
'sql': management.get_sql_create,
|
||||||
'sqlall': management.get_sql_all,
|
'sqlall': management.get_sql_all,
|
||||||
|
@ -18,8 +20,7 @@ ACTION_MAPPING = {
|
||||||
'sqlsequencereset': management.get_sql_sequence_reset,
|
'sqlsequencereset': management.get_sql_sequence_reset,
|
||||||
'startapp': management.startapp,
|
'startapp': management.startapp,
|
||||||
'startproject': management.startproject,
|
'startproject': management.startproject,
|
||||||
'init': management.init,
|
'validate': management.validate,
|
||||||
'install': management.install,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NO_SQL_TRANSACTION = ('adminindex', 'dbcheck', 'install', 'sqlindexes')
|
NO_SQL_TRANSACTION = ('adminindex', 'dbcheck', 'install', 'sqlindexes')
|
||||||
|
@ -65,7 +66,7 @@ def main():
|
||||||
print_error("An action is required.", sys.argv[0])
|
print_error("An action is required.", sys.argv[0])
|
||||||
if not ACTION_MAPPING.has_key(action):
|
if not ACTION_MAPPING.has_key(action):
|
||||||
print_error("Your action, %r, was invalid." % action, sys.argv[0])
|
print_error("Your action, %r, was invalid." % action, sys.argv[0])
|
||||||
if action in ('createsuperuser', 'init'):
|
if action in ('createsuperuser', 'init', 'validate'):
|
||||||
ACTION_MAPPING[action]()
|
ACTION_MAPPING[action]()
|
||||||
elif action == 'inspectdb':
|
elif action == 'inspectdb':
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -483,6 +483,58 @@ def inspectdb(db_name):
|
||||||
inspectdb.help_doc = "Introspects the database tables in the given database and outputs a Django model module."
|
inspectdb.help_doc = "Introspects the database tables in the given database and outputs a Django model module."
|
||||||
inspectdb.args = "[dbname]"
|
inspectdb.args = "[dbname]"
|
||||||
|
|
||||||
|
class ModelErrorCollection:
|
||||||
|
def __init__(self, outfile=sys.stdout):
|
||||||
|
self.errors = []
|
||||||
|
self.outfile = outfile
|
||||||
|
|
||||||
|
def add(self, opts, error):
|
||||||
|
self.errors.append((opts, error))
|
||||||
|
self.outfile.write("%s.%s: %s\n" % (opts.module_name, opts.object_name, error))
|
||||||
|
|
||||||
|
def validate():
|
||||||
|
"Validates all installed models."
|
||||||
|
from django.core import meta
|
||||||
|
e = ModelErrorCollection()
|
||||||
|
module_list = meta.get_installed_model_modules()
|
||||||
|
for module in module_list:
|
||||||
|
for mod in module._MODELS:
|
||||||
|
opts = mod._meta
|
||||||
|
|
||||||
|
# Do field-specific validation.
|
||||||
|
for f in opts.fields:
|
||||||
|
if isinstance(f, meta.CharField) and f.maxlength in (None, 0):
|
||||||
|
e.add(opts, '"%s" field: CharFields require a "maxlength" attribute.' % f.name)
|
||||||
|
|
||||||
|
# Check admin attribute.
|
||||||
|
if opts.admin is not None and not isinstance(opts.admin, meta.Admin):
|
||||||
|
e.add(opts, '"admin" attribute, if given, must be set to a meta.Admin() instance.')
|
||||||
|
|
||||||
|
# Check ordering attribute.
|
||||||
|
if opts.ordering:
|
||||||
|
for field_name in opts.ordering:
|
||||||
|
if field_name == '?': continue
|
||||||
|
if field_name.startswith('-'):
|
||||||
|
field_name = field_name[1:]
|
||||||
|
try:
|
||||||
|
opts.get_field(field_name, many_to_many=False)
|
||||||
|
except meta.FieldDoesNotExist:
|
||||||
|
e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name)
|
||||||
|
|
||||||
|
# Check core=True, if needed.
|
||||||
|
for rel_opts, rel_field in opts.get_inline_related_objects():
|
||||||
|
try:
|
||||||
|
for f in rel_opts.fields:
|
||||||
|
if f.core:
|
||||||
|
raise StopIteration
|
||||||
|
e.add(rel_opts, "At least one field in %s should have core=True, because it's being edited inline by %s.%s." % (rel_opts.object_name, opts.module_name, opts.object_name))
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
|
||||||
|
num_errors = len(e.errors)
|
||||||
|
print '%s error%s found.' % (num_errors, num_errors != 1 and 's' or '')
|
||||||
|
validate.args = ''
|
||||||
|
|
||||||
def runserver(port):
|
def runserver(port):
|
||||||
"Starts a lightweight Web server for development."
|
"Starts a lightweight Web server for development."
|
||||||
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
|
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
|
||||||
|
@ -492,7 +544,9 @@ def runserver(port):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
def inner_run():
|
def inner_run():
|
||||||
from django.conf.settings import SETTINGS_MODULE
|
from django.conf.settings import SETTINGS_MODULE
|
||||||
print "Starting server on port %s with settings module %r." % (port, SETTINGS_MODULE)
|
print "Validating models..."
|
||||||
|
validate()
|
||||||
|
print "\nStarting server on port %s with settings module %r." % (port, SETTINGS_MODULE)
|
||||||
print "Go to http://127.0.0.1:%s/ for Django." % port
|
print "Go to http://127.0.0.1:%s/ for Django." % port
|
||||||
print "Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows)."
|
print "Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows)."
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue