Index: django/db/models/fields/related.py
===================================================================
--- django/db/models/fields/related.py	(revision 6863)
+++ django/db/models/fields/related.py	(working copy)
@@ -549,7 +549,7 @@
         setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
 
     def formfield(self, **kwargs):
-        defaults = {'form_class': forms.ModelChoiceField, 'queryset': self.rel.to._default_manager.all()}
+        defaults = {'form_class': forms.ModelChoiceField, 'queryset': self.rel.to._default_manager.filter(**self.rel.limit_choices_to)}
         defaults.update(kwargs)
         return super(ForeignKey, self).formfield(**defaults)
 
Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 6863)
+++ django/db/models/query.py	(working copy)
@@ -206,6 +206,7 @@
                     obj = self.model(*row[:index_end])
                 for i, k in enumerate(extra_select):
                     setattr(obj, k[0], row[index_end+i])
+                obj.validate()
                 yield obj
 
     def count(self):
Index: django/db/backends/mysql/base.py
===================================================================
--- django/db/backends/mysql/base.py	(revision 6863)
+++ django/db/backends/mysql/base.py	(working copy)
@@ -97,7 +97,7 @@
     def quote_name(self, name):
         if name.startswith("`") and name.endswith("`"):
             return name # Quoting once is enough.
-        return "`%s`" % name
+        return "`%s`" % name.replace('%', '%%')
 
     def random_function_sql(self):
         return 'RAND()'
Index: django/db/backends/mysql/introspection.py
===================================================================
--- django/db/backends/mysql/introspection.py	(revision 6863)
+++ django/db/backends/mysql/introspection.py	(working copy)
@@ -78,6 +78,7 @@
     FIELD_TYPE.BLOB: 'TextField',
     FIELD_TYPE.CHAR: 'CharField',
     FIELD_TYPE.DECIMAL: 'DecimalField',
+    FIELD_TYPE.NEWDECIMAL: 'DecimalField',
     FIELD_TYPE.DATE: 'DateField',
     FIELD_TYPE.DATETIME: 'DateTimeField',
     FIELD_TYPE.DOUBLE: 'FloatField',
Index: django/core/management/commands/inspectdb.py
===================================================================
--- django/core/management/commands/inspectdb.py	(revision 6863)
+++ django/core/management/commands/inspectdb.py	(working copy)
@@ -1,5 +1,198 @@
+import re
+import keyword
+
 from django.core.management.base import NoArgsCommand, CommandError
 
+
+class Database(object):
+    """Maintains a hash of all tables in the database.
+
+      Used for correcting any duplicate model names and resolving foreign key
+      relationships.
+    """
+
+    def __init__(self):
+        self.models = {}
+
+    def add_model(self, model):
+        self.models[model.table_name] = model
+
+    def get_model(self, table_name):
+        return self.models[table_name]
+
+    def __str__(self):
+        s=''
+        for m in self.models.values():
+            s += str(m) + '\n\n'
+        return s
+
+
+class TableModel(object):
+
+    def __init__(self, database, table_name):
+        self.table_name = table_name
+        self.model_name = self.model_name_for_table(table_name)
+        self.columns = []
+        self.relations = []
+
+        database.add_model(self)
+        self.database = database
+
+    def add_column(self, col_name, type, extra_params, comments):
+        """Add a column."""
+        name = self.field_name_for_column(col_name)
+        self.columns.append({
+            'name': name,
+            'col_name': col_name,
+            'type': type,
+            'extra_params': extra_params,
+            'comments': comments
+        })
+
+    def add_relation(self, col_name, rel_to, null):
+        """Adds a related column.
+
+        We don't resolve the table relation at this point.
+        """
+        name = self.field_name_for_column(col_name)
+        self.relations.append({
+            'name': name,
+            'col_name': col_name,
+            'rel_to': rel_to,
+            'null': null
+        })
+
+    def group_fields(self):
+        """Groups fields and performs other heuristic fixups.
+
+        """
+
+        keys = [f for f in self.columns if f['type'] == 'AutoField' or 'primary_key' in f['extra_params']]
+        ids = [f for f in self.columns if f not in keys and f['name'].endswith('_id')]
+
+        if len(keys) == 0:
+            # use heuristics to locate a candidate primary key from amongst the ids
+            tests=[self.model_name.lower()+'id']
+            if self.model_name.lower().endswith('s'):
+                tests.append(self.model_name.lower()[:-1]+'id')
+
+            for id in ids:
+                if id['name'].replace('_', '') in tests:
+                    id['comments'].append('NOTE: selected as primary_key')
+                    id['extra_params']['primary_key']=True
+                    keys.append(id)
+                    ids.remove(id)
+                    break
+
+        #resolve relations
+        rels=self.relations[:]
+        for r in rels:
+            if r['rel_to'] == self.table_name:
+                related = "'self'"
+            else:
+                related = "'%s'"%self.database.get_model(r['rel_to']).model_name
+            r['related']=related
+
+        #upgrade integer primary keys to autofields if none exists
+        if len([k for k in keys if f['type'] == 'AutoField']) == 0:
+            for k in keys:
+                if k['type'] == 'IntegerField':
+                    k['comments'].append('upgraded from IntegerField')
+                    k['type']='AutoField'
+                    break
+
+        # rename the AutoFields, if it exists, to 'id'
+        for k in keys:
+            if k['type'] == 'AutoField':
+                k['name']='id'       #no comment should be necessary
+                break
+
+        other=[f for f in self.columns if f not in keys and f not in ids]
+
+        return (keys, rels, ids, other)
+
+    def model_name_for_table(self, table):
+        """Compute a Python-friendly Model class name for a given table.
+
+        - converts names to CamelCase
+        - removes non-alphanumberic symbols
+        """
+        model=re.sub(r'\b([a-z])', lambda x: x.group(1).upper(), table)
+        model=re.sub(r'[^A-Za-z0-9]', '', model)
+        return model
+
+    def field_name_for_column(self, col):
+        """Compute a Python-friendly Field name for a given column.
+
+        - converts CamelCase names into lower_case_with_underscores
+        - removes hypens
+        - converts any contiguous sequences of other non-alphanumberic symbols to _
+        - if the field name conflicts with a Python keyword, append '_field'
+        - if the field name starts with a digit, prepend 'f_'
+        """
+
+        field=re.sub(r'[A-Z]+', lambda x: '_'+x.group(0).lower(), col) #convert from CamelCase
+        field=field.replace('-', '') #remove hyphen
+        field=re.sub(r'[^A-Za-z0-9]+', '_', field) #replace non-alphanumberics
+
+        field=re.sub('(^_)|(_$)', '', field) #strip leading underscore
+
+        field=re.sub(r'^([0-9])', r'f_\1', field) #fix field names starting with digits
+
+        if keyword.iskeyword(field):
+            field+='_field' #avoid conflict with Python keywords
+
+        return field
+
+    def _field_as_str(self, f):
+        params = ', '.join(['%s=%r'%p for p in f['extra_params'].items()])
+
+        if f['comments']:
+            comments=' # '+'; '.join(f['comments'])
+        else:
+            comments=''
+
+        return '%s = models.%s(%s)%s'%(f['name'], f['type'], params, comments)
+
+    def _rel_as_str(self, f):
+        if f['null']:
+            return '%s = models.ForeignKey(%r, db_column=%r, null=True, blank=True)'%(f['name'], f['related'], f['col_name'])
+        else:
+            return '%s = models.ForeignKey(%r, db_column=%r)'%(f['name'], f['related'], f['col_name'])
+
+    def __str__(self):
+        s='class %s(models.Model):\n' % self.model_name
+
+        keys, rels, ids, other=self.group_fields()
+        if not keys:
+            s+='    # Warning: this model needs a field with primary_key=True\n\n'
+
+        for f in keys:
+            s+='    %s\n'%self._field_as_str(f)
+        if keys:
+            s+='\n'
+
+        for f in ids:
+            s+='    %s\n'%self._field_as_str(f)
+        if ids:
+            s+='\n'
+
+        for r in rels:
+            s+='    %s\n'%self._rel_as_str(f)
+        if rels:
+            s+='\n'
+
+        for f in other:
+            s+='    %s\n'%self._field_as_str(f)
+        if other:
+            s+='\n'
+
+        s+='    class Meta:\n'
+        s+='        db_table = %r\n' % self.table_name
+
+        return s
+
+
 class Command(NoArgsCommand):
     help = "Introspects the database tables in the given database and outputs a Django model module."
 
@@ -14,18 +207,17 @@
 
     def handle_inspection(self):
         from django.db import connection, get_introspection_module
-        import keyword
 
         introspection_module = get_introspection_module()
 
-        table2model = lambda table_name: table_name.title().replace('_', '')
+        cursor = connection.cursor()
+        database=Database()
 
-        cursor = connection.cursor()
         yield "# This is an auto-generated Django model module."
         yield "# You'll have to do the following manually to clean this up:"
-        yield "#     * Rearrange models' order"
         yield "#     * Make sure each model has one field with primary_key=True"
-        yield "# Feel free to rename the models, but don't rename db_table values or field names."
+        yield "#     * Rename models if desired (by convention, model names are singular)"
+        yield "# Note: do NOT rename db_table or db_column values."
         yield "#"
         yield "# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]'"
         yield "# into your database."
@@ -33,7 +225,8 @@
         yield 'from django.db import models'
         yield ''
         for table_name in introspection_module.get_table_list(cursor):
-            yield 'class %s(models.Model):' % table2model(table_name)
+            model=TableModel(database, table_name)
+
             try:
                 relations = introspection_module.get_relations(cursor, table_name)
             except NotImplementedError:
@@ -43,29 +236,23 @@
             except NotImplementedError:
                 indexes = {}
             for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)):
-                att_name = row[0].lower()
+
+                # This is from Python DB-API spec v2 http://www.python.org/dev/peps/pep-0249/
+                column_name, type_code, display_size, internal_size, precision, scale, null_ok = row
+
                 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'
-                    comment_notes.append('Field renamed because it was a Python reserved word.')
+                extra_params = {'db_column': column_name}  # Holds Field parameters
+                # Always specify the db column name - even if the field name matches the column,
+                # we expect users to fix/refactor their models.
 
+
                 if i in relations:
-                    rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1])
-                    field_type = 'ForeignKey(%s' % rel_to
-                    if att_name.endswith('_id'):
-                        att_name = att_name[:-3]
-                    else:
-                        extra_params['db_column'] = att_name
+                    model.add_relation(column_name, relations[i][1], bool(null_ok))
+
                 else:
                     try:
-                        field_type = introspection_module.DATA_TYPES_REVERSE[row[1]]
+                        field_type = introspection_module.DATA_TYPES_REVERSE[type_code]
                     except KeyError:
                         field_type = 'TextField'
                         comment_notes.append('This field type is a guess.')
@@ -77,44 +264,26 @@
                         extra_params.update(new_params)
 
                     # Add max_length for all CharFields.
-                    if field_type == 'CharField' and row[3]:
-                        extra_params['max_length'] = row[3]
+                    if field_type == 'CharField' and internal_size:
+                        extra_params['max_length'] = internal_size
 
                     if field_type == 'DecimalField':
-                        extra_params['max_digits'] = row[4]
-                        extra_params['decimal_places'] = row[5]
+                        extra_params['max_digits'] = precision
+                        extra_params['decimal_places'] = scale
 
                     # Add primary_key and unique, if necessary.
-                    column_name = extra_params.get('db_column', att_name)
                     if column_name in indexes:
                         if indexes[column_name]['primary_key']:
                             extra_params['primary_key'] = True
                         elif indexes[column_name]['unique']:
                             extra_params['unique'] = True
 
-                    field_type += '('
-
-                # Don't output 'id = meta.AutoField(primary_key=True)', because
-                # that's assumed if it doesn't exist.
-                if att_name == 'id' and field_type == 'AutoField(' and extra_params == {'primary_key': True}:
-                    continue
-
                 # Add 'null' and 'blank', if the 'null_ok' flag was present in the
                 # table description.
-                if row[6]: # If it's NULL...
+                if null_ok: # If it's NULL...
                     extra_params['blank'] = True
-                    if not field_type in ('TextField(', 'CharField('):
+                    if not field_type in ('TextField', 'CharField'):
                         extra_params['null'] = True
 
-                field_desc = '%s = models.%s' % (att_name, field_type)
-                if extra_params:
-                    if not field_desc.endswith('('):
-                        field_desc += ', '
-                    field_desc += ', '.join(['%s=%r' % (k, v) for k, v in extra_params.items()])
-                field_desc += ')'
-                if comment_notes:
-                    field_desc += ' # ' + ' '.join(comment_notes)
-                yield '    %s' % field_desc
-            yield '    class Meta:'
-            yield '        db_table = %r' % table_name
-            yield ''
+                model.add_column(column_name, field_type, extra_params, comment_notes)
+        yield str(database)
Index: django/contrib/databrowse/datastructures.py
===================================================================
--- django/contrib/databrowse/datastructures.py	(revision 6863)
+++ django/contrib/databrowse/datastructures.py	(working copy)
@@ -133,7 +133,10 @@
 class EasyInstanceField(object):
     def __init__(self, easy_model, instance, field):
         self.model, self.field, self.instance = easy_model, field, instance
-        self.raw_value = getattr(instance.instance, field.name)
+	try:
+		self.raw_value = getattr(instance.instance, field.name)
+	except models.ObjectDoesNotExist, e:
+		self.raw_value = e
 
     def __repr__(self):
         return smart_str(u'<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
@@ -148,7 +151,7 @@
         # module level.
         if self.field.rel:
             if isinstance(self.field.rel, models.ManyToOneRel):
-                objs = getattr(self.instance.instance, self.field.name)
+	        objs = getattr(self.instance.instance, self.field.name)
             elif isinstance(self.field.rel, models.ManyToManyRel): # ManyToManyRel
                 return list(getattr(self.instance.instance, self.field.name).all())
         elif self.field.choices:
Index: django/contrib/databrowse/templates/databrowse/object_detail.html
===================================================================
--- django/contrib/databrowse/templates/databrowse/object_detail.html	(revision 6863)
+++ django/contrib/databrowse/templates/databrowse/object_detail.html	(working copy)
@@ -15,7 +15,7 @@
 <td>
 {% if field.urls %}
 {% for value, url in field.urls %}
-{% if url %}<a href="{{ url }}">{% endif %}{{ value|escape }}{% if url %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
+{% if url %}<a href="{{ url }}">{% endif %}{{ value|escape|linebreaksbr }}{% if url %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
 {% endfor %}
 {% else %}None{% endif %}
 </td>
Index: django/contrib/databrowse/templates/databrowse/base.html
===================================================================
--- django/contrib/databrowse/templates/databrowse/base.html	(revision 6863)
+++ django/contrib/databrowse/templates/databrowse/base.html	(working copy)
@@ -34,7 +34,7 @@
 .modelgroup h2 { font-size:1.2em; margin:0; }
 .modelgroup h2 a { display: block; padding: 0.83em 20px; }
 .modelgroup h2 a:hover { text-decoration: none; color: #fff; }
-.modelgroup p { float:left; margin:-2.65em 0 0 14em; position:relative; }
+.modelgroup p { float:left; margin:-2.65em 0 0 25em; position:relative; }
 .modelgroup p a { white-space:nowrap; }
 .modelgroup a.more { color:#999; }
 .modelgroup:hover { background:#5b80b2; color:#becfe5; }

