Index: django/core/management/commands/syncdb.py
===================================================================
--- django/core/management/commands/syncdb.py	(revision 8319)
+++ django/core/management/commands/syncdb.py	(working copy)
@@ -61,6 +61,9 @@
             app_name = app.__name__.split('.')[-2]
             model_list = models.get_models(app)
             for model in model_list:
+                # Add model defined schema tables if anny
+                if model._meta.db_schema:
+                    tables += connection.introspection.schema_table_names(model._meta.db_schema)
                 # 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)
Index: django/core/management/sql.py
===================================================================
--- django/core/management/sql.py	(revision 8319)
+++ django/core/management/sql.py	(working copy)
@@ -84,6 +84,9 @@
     references_to_delete = {}
     app_models = models.get_models(app)
     for model in app_models:
+        # Find aditional tables in model defined schemas
+        if model._meta.db_schema:
+            table_names += connection.introspection.get_schema_table_list(cursor, model._meta.db_schema) 
         if cursor and connection.introspection.table_name_converter(model._meta.db_table) in table_names:
             # The table exists, so it needs to be dropped
             opts = model._meta
Index: django/db/backends/__init__.py
===================================================================
--- django/db/backends/__init__.py	(revision 8319)
+++ django/db/backends/__init__.py	(working copy)
@@ -225,6 +225,13 @@
         """
         raise NotImplementedError()
 
+    def prep_db_table(self, db_schema, db_table):
+        """
+        Prepares and formats the table name if neccesary.
+        Just returns the db_table if not supported
+        """
+        return db_table
+
     def random_function_sql(self):
         """
         Returns a SQL expression that returns a random value.
@@ -381,6 +388,14 @@
         "Returns a list of names of all tables that exist in the database."
         cursor = self.connection.cursor()
         return self.get_table_list(cursor)
+    
+    def get_schema_table_list(self, cursor, schema):
+        return []
+    
+    def schema_table_names(self, schema):
+        "Returns a list of names of all tables that exist in the database schema."
+        cursor = self.connection.cursor()
+        return self.get_schema_table_list(cursor, schema)
 
     def django_table_names(self, only_existing=False):
         """
Index: django/db/backends/creation.py
===================================================================
--- django/db/backends/creation.py	(revision 8319)
+++ django/db/backends/creation.py	(working copy)
@@ -243,8 +243,14 @@
                     tablespace_sql = ''
             else:
                 tablespace_sql = ''
+            # Use original db_table in index name if schema is provided
+            if model._meta.db_schema:
+                index_table_name = model._meta._db_table
+            else:
+                index_table_name = model._meta.db_table
+                
             output = [style.SQL_KEYWORD('CREATE INDEX') + ' ' +
-                style.SQL_TABLE(qn('%s_%s' % (model._meta.db_table, f.column))) + ' ' +
+                style.SQL_TABLE(qn('%s_%s' % (index_table_name, f.column))) + ' ' +
                 style.SQL_KEYWORD('ON') + ' ' +
                 style.SQL_TABLE(qn(model._meta.db_table)) + ' ' +
                 "(%s)" % style.SQL_FIELD(qn(f.column)) +
Index: django/db/backends/mysql/base.py
===================================================================
--- django/db/backends/mysql/base.py	(revision 8319)
+++ django/db/backends/mysql/base.py	(working copy)
@@ -106,8 +106,12 @@
     def quote_name(self, name):
         if name.startswith("`") and name.endswith("`"):
             return name # Quoting once is enough.
-        return "`%s`" % name
+        # add support for tablenames passed that also have their schema in their name
+        return "`%s`" % name.replace('.','`.`') 
 
+    def prep_db_table(self, db_schema, db_table):
+        return "%s.%s" % (db_schema, db_table)
+
     def random_function_sql(self):
         return 'RAND()'
 
Index: django/db/backends/mysql/introspection.py
===================================================================
--- django/db/backends/mysql/introspection.py	(revision 8319)
+++ django/db/backends/mysql/introspection.py	(working copy)
@@ -32,6 +32,10 @@
         cursor.execute("SHOW TABLES")
         return [row[0] for row in cursor.fetchall()]
 
+    def get_schema_table_list(self, cursor, schema):
+        cursor.execute("SHOW TABLES FROM %s" % self.connection.ops.quote_name(schema))
+        return [schema + "." + row[0] for row in cursor.fetchall()]
+    
     def get_table_description(self, cursor, table_name):
         "Returns a description of the table, with the DB-API cursor.description interface."
         cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name))
Index: django/db/models/options.py
===================================================================
--- django/db/models/options.py	(revision 8319)
+++ django/db/models/options.py	(working copy)
@@ -21,7 +21,7 @@
 DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering',
                  'unique_together', 'permissions', 'get_latest_by',
                  'order_with_respect_to', 'app_label', 'db_tablespace',
-                 'abstract')
+                 'abstract', 'db_schema')
 
 class Options(object):
     def __init__(self, meta, app_label=None):
@@ -29,6 +29,7 @@
         self.module_name, self.verbose_name = None, None
         self.verbose_name_plural = None
         self.db_table = ''
+        self.db_schema = ''
         self.ordering = []
         self.unique_together =  []
         self.permissions =  []
@@ -95,6 +96,14 @@
             self.db_table = "%s_%s" % (self.app_label, self.module_name)
             self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
 
+        # Patch db_table with the schema if provided and allowed
+        if self.db_schema:
+            # Store original db_table in a save place first
+            self._db_table = self.db_table
+            self.db_table = connection.ops.prep_db_table(self.db_schema, self.db_table)
+            # If no changes were done then backend don't support schemas
+            if self._db_table == self.db_table:
+                self.db_schema = ''
 
     def _prepare(self, model):
         if self.order_with_respect_to:
Index: docs/model-api.txt
===================================================================
--- docs/model-api.txt	(revision 8319)
+++ docs/model-api.txt	(working copy)
@@ -1207,6 +1207,18 @@
 that aren't allowed in Python variable names -- notably, the hyphen --
 that's OK. Django quotes column and table names behind the scenes.
 
+``db_schema``
+-----------------
+
+**New in Django development version**
+
+The name of the database schema to use for the model. If the backend
+doesn't support multiple schemas, this options is ignored.
+
+If this is used Django will prefix any table names with the schema name.
+For MySQL Django would use ``db_schema + '.' + db_table``.
+
+
 ``db_tablespace``
 -----------------
 
Index: tests/modeltests/schemas/__init__.py
===================================================================
Index: tests/modeltests/schemas/models.py
===================================================================
--- tests/modeltests/schemas/models.py	(revision 0)
+++ tests/modeltests/schemas/models.py	(revision 0)
@@ -0,0 +1,74 @@
+# coding: utf-8
+
+from django.db import models
+
+
+class Blog(models.Model):
+    "Model in default schema"
+    name = models.CharField(max_length=50)
+
+    
+class Entry(models.Model):
+    "Model in custom schema that reference the default"
+    blog = models.ForeignKey(Blog)    
+    title = models.CharField(max_length=50)
+    
+    class Meta:
+        "using custom db_table as well"
+        db_table='schema_blog_entries'
+        db_schema = 'test_django'
+        
+
+class Comment(models.Model):
+    "Model in the default schema that references the custom"
+    entry = models.ForeignKey(Entry)
+    text = models.CharField(max_length=50)
+
+__test__ = {'API_TESTS': """
+# Nothing in there yet
+>>> Blog.objects.all()
+[]
+
+# Create a blog
+>>> b = Blog(name='Test')
+>>> b.save()
+
+# Verify that we got an ID
+>>> b.id
+1
+
+# Create entry
+>>> e = Entry(blog=b, title='Test entry')
+>>> e.save()
+>>> e.id
+1
+
+# Create Comments
+>>> c1 = Comment(entry=e, text='nice entry')
+>>> c1.save()
+>>> c2 = Comment(entry=e, text='really like it')
+>>> c2.save()
+
+
+>>> from django.conf import settings
+>>> from django.db import connection, models
+
+# Test if we support schemas and can find the table if so
+>>> if e._meta.db_schema:
+...     tables = connection.introspection.schema_table_names(e._meta.db_schema)
+... else:
+...     tables = connection.introspection.table_names()
+>>> if connection.introspection.table_name_converter(e._meta.db_table) in tables:
+...     print "ok"
+... else:
+...     print "schema=" + e._meta.db_schema
+ok
+
+# Test that mysql backend doesn't drop the schema
+>>> if settings.DATABASE_ENGINE == 'mysql':
+...     if e._meta.db_schema != 'test_django':
+...         print "shouldn't drop or modify schema"
+
+#Done
+"""
+}
