from django.conf import settings
from django.contrib.auth.models import User
from django.db import models, connection, transaction
from django.utils.translation import ugettext as _
from django.core.validators import RegexValidator
from django.forms import ValidationError

import ensure_installation
import signals

class ClassProperty(property):
    def __get__(self, cls, owner):
        return self.fget.__get__(None, owner)()

def is_schema_aware(cls):
    return cls._meta.auto_created and cls._meta.auto_created._is_schema_aware
    
models.Model._is_schema_aware = ClassProperty(classmethod(is_schema_aware))


class Schema(models.Model):
    name = models.CharField(max_length=128, help_text=_(u'The display name of the schema.'))
    schema = models.CharField(max_length=36, unique=True,
        validators=[RegexValidator(
            regex='^[a-z][a-z_]*$',
            message=_(u'May only contain lowercase letters and underscores. Must start with a letter.')
        )],
        help_text=_(u'The internal name of the schema. May not be changed after creation.'),
    )
    
    class Meta:
        app_label = 'multi_schema'
    
    def __unicode__(self):
        return self.name
    
    def save(self, *args, **kwargs):
        self._meta.get_field_by_name('schema')[0].run_validators(self.schema)
        
        if self.pk and Schema.objects.get(pk=self.pk).schema != self.schema:
                raise ValidationError(_(u'Schema value may not be changed after creation.'))
        
        self.create_schema()
        
        return super(Schema, self).save(*args, **kwargs)
        
    def create_schema(self, cursor=None):
        if not cursor:
            cursor = connection.cursor()
        cursor.execute("SELECT schema_name FROM information_schema.schemata WHERE schema_name = %s", [self.schema])
        if not cursor.fetchone():
            cursor.execute("SELECT clone_schema('__template__', %s);", [self.schema])
            transaction.commit_unless_managed()
            signals.schema_created.send(sender=self, schema=self.schema)
    
    def activate(self, cursor=None):
        signals.schema_pre_activate.send(sender=self, schema=self.schema)
        (cursor or connection.cursor()).execute('SET search_path TO "%s",public' % self.schema)
        signals.schema_post_activate.send(sender=self, schema=self.schema)
    
    def deactivate(self, cursor=None):
        signals.schema_pre_activate.send(sender=self, schema=self.schema)
        (cursor or connection.cursor()).execute('SET search_path TO public')
        signals.schema_post_activate.send(sender=self, schema=self.schema)

template_schema = Schema(name="Template Schema", schema="__template__")

class UserSchema(models.Model):
    user = models.ForeignKey(User, related_name='schemata')
    schema = models.ForeignKey(Schema, related_name='users')
    
    class Meta:
        app_label = 'multi_schema'
    
    def __unicode__(self):
        return u"%s : %s" % (self.user, self.schema)

@@ -49,28 +49,16 @@
 trib
-.auth.models
  import 
 User
@@ -53,20 +53,20 @@
  import 
-User
+auth
 %0Afrom dj
@@ -298,16 +298,410 @@
 ignals%0A%0A
+try:%0A    User = auth.get_user_model()%0Aexcept:%0A    # Was getting an error where auth.models could not be found.%0A    import django.contrib.auth.models%0A    User = auth.models.User%0A    %0A%0A# This is a bit of fancy trickery to stick the property _is_schema_aware%0A# on every model class, returning False, unless it has been explicitly%0A# set to True in the model definition (see base.py for examples).%0A%0A
 class Cl
@@ -911,21 +911,17 @@
 a_aware%0A
-    
 %0A
+
 models.M
@@ -990,16 +990,16 @@
 are))%0A%0A%0A
-
 class Sc
@@ -1014,24 +1014,342 @@
 els.Model):%0A
+    %22%22%22%0A    The Schema model provides an abstraction for a Postgres schema.%0A    %0A    It will take care of creating a cloned copy of the template_schema%0A    when it is created, and also has the ability to activate and deactivate%0A    itself (at the start and end of the request cycle would be a good plan).%0A    %0A    %22%22%22%0A
     name = m
@@ -3320,16 +3320,53 @@
 chema)%0A%0A
+# An in-memory only template schema.%0A
 template
@@ -3458,24 +3458,282 @@
 els.Model):%0A
+    %22%22%22%0A    A relationship between a User and a Schema. A User may be able to%0A    access the data from many schemata, and in that case should be%0A    provided with tools to do so.%0A    %0A    See templates/multi_schema/change_schema.html for an example.%0A    %22%22%22%0A
     user = m

Use the future-proof way of getting the User class. Add some comments.