mapping a class linked with two other classes (AttributeError: 'str' object has no attribute '_sa_instance_state')

2,524 views
Skip to first unread message

Jules Stevenson

unread,
Jun 16, 2011, 3:44:25 AM6/16/11
to sqlal...@googlegroups.com
Hi List,

I have a user class, a contact class, and a googleID class.

the contact class has can have a googleID per user in the system. I'm
trying to map it out as follows:

# ArkContact - clientprojectshot module
orm.mapper(ArkContact, contacts_table, properties={
'notes': orm.relation(ArkNote,
secondary=contact_notes_table,
backref='contacts',
single_parent=True,
cascade="all, delete, delete-orphan"),
'users': orm.relation(ArkUser,
secondary=user_contact_table,
backref='contacts'),
'google_UID': orm.relation(ArkUserContactGUID,
cascade="all, delete",
backref='user')
})

#user contact google_GUID
user_contact_UID = sa.Table('user_contact_UID_table', meta.metadata,
sa.Column('user_id', sa.types.Integer, sa.ForeignKey('users.id'),
primary_key=True),
sa.Column('contact_id', sa.types.Integer,
sa.ForeignKey('contacts.id'), primary_key=True),
sa.Column('google_UID', sa.types.String(length = 1024))
)

class ArkUserContactGUID(object):
def __init__(self):
pass

orm.mapper(ArkUserContactGUID, user_contact_UID)

This raises two issues, the first is that an instrumented list is
returned for the google_UID paramter on the contact object, whereas
there should only ever be one (since as an operator there is only ever
one user signed in - you).

The second is it outright errors :), presumably because my mapping is off:

File 'C:\\ark\\ark\\controllers\\contacts.py', line 368 in initial_sync
contact_sync.initial_sync()
File 'C:\\ark\\ark\\arkTools\\arkGoogle.py', line 121 in initial_sync
self.add_contact_to_google(contact)
File 'C:\\ark\\ark\\arkTools\\arkGoogle.py', line 259 in add_contact_to_google
data.google_UID.append(entry.get_id())
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\collections.py',
line 952 in append
item = __set(self, item, _sa_initiator)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\collections.py',
line 927 in __set
item = getattr(executor, 'fire_append_event')(item, _sa_initiator)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\collections.py',
line 618 in fire_append_event
item, initiator)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\attributes.py',
line 741 in fire_append_event
value = fn(state, value, initiator or self)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\unitofwork.py',
line 35 in append
item_state = attributes.instance_state(item)
AttributeError: 'str' object has no attribute '_sa_instance_state'

Many thanks for any help!

Jules

King Simon-NFHD78

unread,
Jun 16, 2011, 9:04:53 AM6/16/11
to sqlal...@googlegroups.com

For one-to-one relationships, you should supply "uselist=False" to your
relationship:

http://www.sqlalchemy.org/docs/orm/relationships.html#one-to-one

You're passing a string (presumably the result of entry.get_id()) where
SA is expecting an instance of a mapped class. I haven't looked at your
mapping in detail, but rather than this:

data.google_UID.append(entry.get_id())

you probably want something like this:

obj = ArkUserContactGUID(google_UID=entry.get_id())
data.google_UID.append(obj)

(If I've misunderstood your mapping, these class names are probably
wrong)

Hope that helps,

Simon

Jules Stevenson

unread,
Jun 16, 2011, 9:40:07 AM6/16/11
to sqlal...@googlegroups.com
Hi Simon, thank you very much for your help (again!), and yes, that's
how I'm using the mapping :).

I'm now getting an SQL error, I think because the user is not being
pulled automatically through when trying to add the
ArkUserContactGUID:

OperationalError: (OperationalError) (1364, "Field 'user_id' doesn't
have a default value") 'INSERT INTO `user_contact_UID_table`
(contact_id, uid) VALUES (%s, %s)' (2L,
'http://www.google.com/m8/feeds/contacts/jules%40kettlestudio.co.uk/base/7c5456c108b2111b')

File 'C:\\ark\\ark\\controllers\\contacts.py', line 368 in initial_sync
contact_sync.initial_sync()
File 'C:\\ark\\ark\\arkTools\\arkGoogle.py', line 121 in initial_sync
self.add_contact_to_google(contact)

File 'C:\\ark\\ark\\arkTools\\arkGoogle.py', line 263 in add_contact_to_google
meta.Session.commit()
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\scoping.py',
line 113 in do
return getattr(self.registry(), name)(*args, **kwargs)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\session.py',
line 617 in commit
self.transaction.commit()
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\session.py',
line 293 in commit
self._prepare_impl()
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\session.py',
line 277 in _prepare_impl
self.session.flush()
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\session.py',
line 1473 in flush
self._flush(objects)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\session.py',
line 1542 in _flush
flush_context.execute()
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\unitofwork.py',
line 327 in execute
rec.execute(self)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\unitofwork.py',
line 471 in execute
uow
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\orm\\mapper.py',
line 2163 in _save_obj
execute(statement, params)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\engine\\base.py',
line 1358 in execute
params)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\engine\\base.py',
line 1491 in _execute_clauseelement
compiled_sql, distilled_params
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\engine\\base.py',
line 1599 in _execute_context
context)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\engine\\base.py',
line 1592 in _execute_context
context)
File 'C:\\ark\\env_x64\\lib\\site-packages\\sqlalchemy-0.7.1-py2.6.egg\\sqlalchemy\\engine\\default.py',
line 325 in do_execute
cursor.execute(statement, parameters)
File 'C:\\ark\\env_x64\\lib\\site-packages\\MySQLdb\\cursors.py', line
173 in execute
self.errorhandler(self, exc, value)
File 'C:\\ark\\env_x64\\lib\\site-packages\\MySQLdb\\connections.py',
line 36 in defaulterrorhandler
raise errorclass, errorvalue
OperationalError: (OperationalError) (1364, "Field 'user_id' doesn't
have a default value") 'INSERT INTO `user_contact_UID_table`
(contact_id, uid) VALUES (%s, %s)' (2L,
'http://www.google.com/m8/feeds/contacts/jules%40kettlestudio.co.uk/base/7c5456c108b2111b')

I think this is because the contacts object uses a many to many
relationship (a contact can belong to any or all users), code as
follows:

# ArkContact - clientprojectshot module
orm.mapper(ArkContact, contacts_table, properties={
'notes': orm.relation(ArkNote,
secondary=contact_notes_table,
backref='contacts',
single_parent=True,
cascade="all, delete, delete-orphan"),
'users': orm.relation(ArkUser,
secondary=user_contact_table,
backref='contacts'),
'google_UID': orm.relation(ArkUserContactGUID,
cascade="all, delete",

uselist=False,
backref='user')
})


I'm thinking I should join between the user and ArkUserContactGUID
somehow, but don't know how...

Many thanks,

Jules

> --
> You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
> To post to this group, send email to sqlal...@googlegroups.com.
> To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
>
>

Jules Stevenson

unread,
Jun 16, 2011, 10:12:55 AM6/16/11
to sqlal...@googlegroups.com
Ack, ignore :). There was no direct relationship to the user at all,
doh. So I'm passing that into the ArkUserContactGUID construction, and
all works well.

Thanks again for the help, much appreciated.

Jules

Reply all
Reply to author
Forward
0 new messages