I am trying to implement a common login across multiple applications. It occurred to me that the applications needed to share the auth tables, so I migrated from sqlite to Postgresql. The migration appears to be working with my Purchasing application.
I pruned all the application table defs from db.py and copied it to the welcome app. When I try to run the welcome app I get an exception. The error snapshot says: <class 'psycopg2.ProgrammingError'>(relation "auth_group" already exists The traceback says: Traceback (most recent call last): File "/home/cjk/plag/gluon/restricted.py", line 192, in restricted exec ccode in environment File "/home/cjk/plag/applications/welcome/models/db.py", line 123, in <module> auth.define_tables() # creates all needed tables File "/home/cjk/plag/gluon/tools.py", line 1232, in define_tables format = '%(role)s (%(id)s)')) File "/home/cjk/plag/gluon/dal.py", line 4311, in define_table polymodel=polymodel) File "/home/cjk/plag/gluon/dal.py", line 642, in create_table self.create_sequence_and_triggers(query,table) File "/home/cjk/plag/gluon/dal.py", line 1720, in create_sequence_and_triggers self.execute(query) File "/home/cjk/plag/gluon/dal.py", line 1262, in execute return self.log_execute(*a, **b) File "/home/cjk/plag/gluon/dal.py", line 1257, in log_execute ret = self.cursor.execute(*a,**b) ProgrammingError: relation "auth_group" already exists db.py looks like this: # -*- coding: utf-8 -*- db = DAL('postgres://theuser:password@localhost:5432/mydb', migrate=False) # by default give a view/generic.extension to all actions from localhost # none otherwise. a pattern can be 'controller/function.extension' response.generic_patterns = ['*'] if request.is_local else [] from gluon.tools import Mail, Auth, Crud, Service, PluginManager, prettydate mail = Mail() # mailer auth = Auth(db) # authentication/ authorization crud = Crud(db) # for CRUD helpers using auth service = Service() # for json, xml, jsonrpc, xmlrpc, amfrpc plugins = PluginManager() # for configuring plugins mail.settings.server = 'logging' or 'smtp.gmail.com:587' # your SMTP server mail.settings.sender = 'cjk...@gmail.com' # your email mail.settings.login = 'None' # your credentials or None auth.settings.hmac_key = 'sha512:6db047cf-363a-4d4e-b697- c229c6ef8752' # before define_tables() db.define_table('tenants', Field('name', length=64, default=''), migrate=False) db.define_table( 'auth_user', Field('first_name', length=128, default='', label='First name', required=True, comment=SPAN('Required', _style='color:orange;')), Field('middle_name', length=128, default='', label='Middle name'), Field('last_name', length=128, default='', label='Last name'), Field('generation', length=16, default='', label='Generation'), Field('address', length=128, default=''), Field('address_2', length=128, default=''), Field('city', length=32, default=''), Field('state', length=32, default=''), Field('zip', length=12, default=''), Field('email', length=128, default='', unique=True), Field('password', 'password', length=512, writable=False, readable=False, label='Password'), Field('registration_key', length=512, writable=False, readable=False, default=''), Field('reset_password_key', length=512, writable=False, readable=False, default=''), Field('registration_id', length=512, writable=False, readable=False, default=''), Field('land_line', length=32, default=''), Field('mobile', length=32, default=''), Field('fax', length=32, default=''), Field('is_staff', 'boolean', default=False), Field('is_trainer', 'boolean', default=False), Field('created_on', 'datetime', default=request.now), Field('created_by', 'integer'), Field('updated_on', 'datetime', default=request.now), Field('updated_by', 'integer'), Field('is_active', 'boolean', default=True), Field('tenant_link', db.tenants), ## Field('request_tenant', 'integer'), format='%(first_name)s %(middle_name)s %(last_name)s % (generation)s', migrate=False ) db.auth_user.first_name.requires = \ IS_NOT_EMPTY(error_message='First name is required') db.auth_user.last_name.requires = \ IS_NOT_EMPTY(error_message='Last name is required') db.auth_user.password.requires = [IS_STRONG(), CRYPT()] db.auth_user.email.requires = [IS_EMPTY_OR( [IS_EMAIL(error_message=auth.messages.invalid_email), IS_NOT_IN_DB(db, 'auth_user.email')])] db.auth_user.tenant_link.requires = IS_IN_DB(db, 'tenants.id', '%(name)s', zero= "Choose") db.auth_user.is_active.readable = db.auth_user.is_active.writable = False db.auth_user.created_on.readable = db.auth_user.created_on.writable = False db.auth_user.created_by.readable = db.auth_user.created_by.writable = False db.auth_user.updated_on.readable = db.auth_user.updated_on.writable = False db.auth_user.updated_by.readable = db.auth_user.updated_by.writable = False db.auth_user.tenant_link.readable = db.auth_user.tenant_link.writable = False signature = db.Table( db, 'signature', Field( 'created_on', 'datetime', default=request.now, readable=False, writable=False), Field('created_by', db.auth_user, default=auth.user_id, readable=False, writable=False), Field('updated_on', 'datetime', update=request.now, readable=False, writable=False), Field('updated_by', db.auth_user, update=auth.user_id, readable=False, writable=False), Field('is_active', 'boolean', default=True, readable=False, writable=False) ) auth.define_tables() # creates all needed tables auth.settings.reset_password_requires_verification = True auth.messages.reset_password = 'Click on the link http://'+request.env.http_host+URL('default','user',args=['reset_password'])+'/%(key)s to reset your password' crud.settings.auth = auth # =auth to enforce authorization on crud db.define_table('tenant_groups', Field('tenant_id', db.tenants), Field('group_id', db.auth_group), Field('is_default', 'boolean', default=False), migrate=False ) db.tenant_groups.tenant_id.requires = IS_IN_DB(db, db.tenants.id, '%(name)s', zero = 'Choose a tenant') db.tenant_groups.group_id.requires = IS_IN_DB(db, db.auth_group.id, '%(role)', zero = 'Chose a group') db.auth_permission.table_name.requires = IS_IN_SET(db.tables)