django-tenant-schemas icon indicating copy to clipboard operation
django-tenant-schemas copied to clipboard

Using django-tenant-schemas doesn't apply my AUTH_USER_MODEL when running migrate_schema

Open danolsen opened this issue 10 years ago • 16 comments

Do I need to do something special to get django-tenant-schemas to work with my custom user model. I am following Django's directions to use AUTH_USER_MODEL. Before I started using django-tenant-schemas the migrations worked fine. Now they don't work with django-tenant-schemas.

When I run migrate_schemas I get the following error. The migration contains the same migration code that worked before I started using django-tenant-schemas.

=== Running migrate for schema public
Operations to perform:
  Synchronize unmigrated apps: clients, tenant_schemas
  Apply all migrations: admin, contenttypes, hub, auth, sessions
Synchronizing apps without migrations:
  Creating tables...
    Creating table clients_client
  Installing custom SQL...
  Installing indexes...
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying hub.0001_initial... OK
  Applying admin.0001_initial...Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
    utility.execute()
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/tenant_schemas/management/commands/migrate_schemas.py", line 24, in run_from_argv
    super(MigrateSchemasCommand, self).run_from_argv(argv)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/core/management/base.py", line 338, in execute
    output = self.handle(*args, **options)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/tenant_schemas/management/commands/migrate_schemas.py", line 34, in handle
    self.run_migrations(self.schema_name, settings.SHARED_APPS)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/tenant_schemas/management/commands/migrate_schemas.py", line 61, in run_migrations
    command.execute(*self.args, **defaults)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/core/management/base.py", line 338, in execute
    output = self.handle(*args, **options)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 161, in handle
    executor.migrate(targets, plan, fake=options.get("fake", False))
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/db/migrations/executor.py", line 68, in migrate
    self.apply_migration(migration, fake=fake)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/db/migrations/executor.py", line 102, in apply_migration
    migration.apply(project_state, schema_editor)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/db/backends/schema.py", line 82, in __exit__
    self.execute(sql)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/db/backends/schema.py", line 102, in execute
    cursor.execute(sql, params)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/db/backends/utils.py", line 81, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File ".../Projects/python-virtual-env/mlm27/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "hub_mlmuser" does not exist

danolsen avatar Feb 11 '15 00:02 danolsen

I'm having the exact same issue when trying to use a custom user model with django-tenant-schemas. Have you perhaps found a solution in the meantime?

GlennV avatar Feb 25 '15 16:02 GlennV

I maybe late to the party, but I ran into the same error which is not Django Nose specific. The error is related to the order of the installed apps in settings. If your using a custom model you need to make sure that the initial table created is your user model. You would get the same error without Django Nose when running migrations for the first time also.

glynjackson avatar Apr 27 '15 15:04 glynjackson

@glynjackson I am late to this part too and believe that I might be seeing a similar issue (just posted an Issue, then saw this one). Can you expand on your comment slightly (maybe an example)? I am using

SHARED_APPS = (
    'tenant_schemas',  # mandatory
    'customers', # you must list the app where your tenant model resides in

    'django.contrib.contenttypes',

    # everything below here is optional
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.admin',
)

TENANT_APPS = (
    # The following Django contrib apps must be in TENANT_APPS
    'django.contrib.contenttypes',

    # your tenant-specific apps
    'customauth',
)

INSTALLED_APPS = list(set(SHARED_APPS + TENANT_APPS))

where customauth contains the custom user.

Any ideas or help would be very greatly appreciated.

(@GlennV or @danolsen, did you guys get this working?)

brechmos avatar May 26 '15 16:05 brechmos

As there are a number of ways to do custom user could you post a copy of your models file.

tomturner avatar May 26 '15 18:05 tomturner

Here is my customauth/models.py file:

$ cat customauth/models.py
from django.db import models

# Create your models here.
from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


class MyUserManager(BaseUserManager):
    def create_user(self, email, date_of_birth, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
            date_of_birth=date_of_birth,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, date_of_birth, password):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(email,
            password=password,
            date_of_birth=date_of_birth
        )
        user.is_admin = True
        user.save(using=self._db)
        return user


class MyUser(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    date_of_birth = models.DateField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['date_of_birth']

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __str__(self):              # __unicode__ on Python 2
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

The error is:

$ python manage.py makemigrations customauth
Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
    utility.execute()
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 330, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/base.py", line 390, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/base.py", line 441, in execute
    output = self.handle(*args, **options)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 63, in handle
    loader = MigrationLoader(None, ignore_no_migrations=True)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/db/migrations/loader.py", line 47, in __init__
    self.build_graph()
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/db/migrations/loader.py", line 287, in build_graph
    parent = self.check_key(parent, key[0])
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/db/migrations/loader.py", line 165, in check_key
    raise ValueError("Dependency on unknown app: %s" % key[0])
ValueError: Dependency on unknown app: customauth

and the relevant part of the settings.py

TENANT_MODEL = "customers.Client"
AUTH_USER_MODEL = 'customauth.MyUser'

# Application definition

SHARED_APPS = (
    'tenant_schemas',  # mandatory
    'customers', # you must list the app where your tenant model resides in

    'django.contrib.contenttypes',

    # everything below here is optional
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.admin',
)

TENANT_APPS = (
    # The following Django contrib apps must be in TENANT_APPS
    'django.contrib.contenttypes',

    # your tenant-specific apps
    'customauth',
)

INSTALLED_APPS = list(set(SHARED_APPS + TENANT_APPS))

(as an aside, @tomturner , I am using your version of django-tenant-schemas)

brechmos avatar May 26 '15 19:05 brechmos

Have you tried putting the customauth model in the shared app as well as the tenant one.

When a user logs into a tenant they will only be able to use the users store in that tenant customauth not the shared one.

Below is what I think it should be

Let me know if it works

SHARED_APPS = (
    'tenant_schemas',  # mandatory
    'customers', # you must list the app where your tenant model resides in

    'django.contrib.contenttypes',

    # everything below here is optional
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.admin',
    'customauth',
)

TENANT_APPS = (
    # The following Django contrib apps must be in TENANT_APPS
    'django.contrib.contenttypes',
    'django.contrib.auth',


    # your tenant-specific apps
    'customauth',
)

tomturner avatar May 26 '15 19:05 tomturner

Sadly it didn't seem to work:

TENANT_MODEL = "customers.Client"
AUTH_USER_MODEL = 'customauth.MyUser'

# Application definition

SHARED_APPS = (
    'tenant_schemas',  # mandatory
    'customers', # you must list the app where your tenant model resides in

    'django.contrib.contenttypes',

    # everything below here is optional
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.admin',
    'customauth',
)

TENANT_APPS = (
    # The following Django contrib apps must be in TENANT_APPS
    'django.contrib.contenttypes',
    'django.contrib.auth',

    # your tenant-specific apps
    'customauth',
)

INSTALLED_APPS = list(set(SHARED_APPS + TENANT_APPS))

it is giving me the same error:

$ python manage.py makemigrations customauth
Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
    utility.execute()
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 330, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/base.py", line 390, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/base.py", line 441, in execute
    output = self.handle(*args, **options)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 63, in handle
    loader = MigrationLoader(None, ignore_no_migrations=True)
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/db/migrations/loader.py", line 47, in __init__
    self.build_graph()
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/db/migrations/loader.py", line 287, in build_graph
    parent = self.check_key(parent, key[0])
  File "/home/odroid/Documents/django/thetest/env/lib/python3.4/site-packages/django/db/migrations/loader.py", line 165, in check_key
    raise ValueError("Dependency on unknown app: %s" % key[0])
ValueError: Dependency on unknown app: customauth

(I can't be the first to try a custom user in django 1.8 with tenant schemas, but I am not sure what would be different). I can post a zip file (minus the env) if that would be helpful. Otherwise, other suggestions? I don't have a deep understanding of the migrations so am finding this hard to decipher.

brechmos avatar May 26 '15 19:05 brechmos

I got it work however I used AbstractUser instead

class UserProfile(AbstractUser):
    company_name = models.CharField(max_length=255, blank=True, null=True)

tomturner avatar May 26 '15 20:05 tomturner

Would you mind posting the full custom user models.py and site settings.py files (for some reason I am still getting the unknown app issue, so I must have something different still)? And did you just do a python manage.py makemigrations or did you do a python manage.py makemigrations customuser and then python manage.py makemigrations?

If I get this going (err, when) I can maybe post a full example somewhere as it might be helpful for others.

brechmos avatar May 26 '15 22:05 brechmos

I haven't had time to do this yet. I will try and do this soon however I am currently at Djangocon EU.

tomturner avatar Jun 01 '15 13:06 tomturner

Just to put this to rest now. I finally figured out one issue and might have been my issue. I was clearing out the migrations directory (including the init.py file). Without the init.py file it was giving me the errors above. When I put the init.py file in there all the migrations ran correctly and database tables were created after the migrate_schemas --shared.

So, I have not fully tested that this will get me past my issues and not sure this will solve world problems but I wanted to note this just for some closure on this.

brechmos avatar Jun 15 '15 17:06 brechmos

I had a similar issue and I discovered that I hadn't run the "makemigrations" for my custom user model before using "python manage.py migrate_schemas --shared".

FlashBanistan avatar Jul 26 '17 00:07 FlashBanistan

also the same problem with custom user model.

nevermorever avatar Mar 03 '18 16:03 nevermorever

This issue still exist. Who is solved this issue?

pije76 avatar Sep 15 '19 00:09 pije76

Hi, any updates on this issue? I am getting the same error which says a relation (part of tenant app) doesn't exist while performing "migrate_schemas --shared"

spsree4u avatar Feb 07 '20 06:02 spsree4u

Hi, any updates on this issue? I am getting the same error which says a relation (part of tenant app) doesn't exist while performing "migrate_schemas --shared"

Hi spsree4U, did you manage to solve this issue ? If not, this is what worked for me

Settings

TENANT_MODEL = "customer.Client" AUTH_USER_MODEL = 'customauth.MyUser'

SHARED_APPS = ( 'tenant_schemas', 'customauth', 'customer', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', )

TENANT_APPS = ( 'customauth', 'django.contrib.contenttypes', )

INSTALLED_APPS = ( 'tenant_schemas', 'customauth', 'customer', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles' )

Migration

  1. python manage.py makemigrations customauth
  2. python manage.py makemigrations customer
  3. python manage.py migrate_schemas --shared

Environment python==3.7 Django==2.2 django-tenant-schemas==3.11.0

NB: Tested also with django==1.11 and django-tenant-schemas==1.9.0

Best of luck.

lesiriam avatar Jul 05 '20 00:07 lesiriam