Hi,
I'm running into a problem illustrated by the code below. The result
is an IntegrityError:
sqlalchemy.exc.IntegrityError: (IntegrityError) null value in column
"group_id" violates not-null constraint
'INSERT INTO groups_owners (owner_id, item_id) VALUES (%(owner_id)s, %
(item_id)s) RETURNING groups_owners.group_id' {'item_id': 1,
'owner_id': 1}
Looking at the stack trace, autoflush is triggerred by the assignments
in GroupOwner.__init__(), but I fail to see why or what to do about
it.
The error appeared when I set a backref with uselist=False on the
GroupOwner.item relationship. I can work around the problem by using a
list instead, although that would make less sense since there's at
most one group per item. Is there an error in my relationship
configuration?
I'm running SA 0.6.6.
==== Code to reproduce the error ====
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy import Table, Column, Integer, Numeric, String,
ForeignKey, MetaData
from sqlalchemy.engine import create_engine
from sqlalchemy.orm import sessionmaker, mapper, relationship, backref
meta = MetaData()
engine = create_engine('postgresql://test:test@localhost/test')
Session = sessionmaker(bind=engine)
session = Session()
owners = Table("owners", meta,
Column('id', Integer, primary_key=True),
Column('name', String)
)
items = Table("items", meta,
Column('id', Integer, primary_key=True),
Column('name', String),
Column('owner_id', Integer, ForeignKey('owners.id'))
)
groups = Table("groups", meta,
Column('id', Integer,primary_key=True),
)
groups_owners = Table("groups_owners", meta,
Column('group_id', Integer,
ForeignKey('groups.id'), primary_key=True),
Column('owner_id', Integer,
ForeignKey('owners.id'), primary_key=True),
Column('item_id', Integer,
ForeignKey('items.id'), nullable=False, unique=True) # notice
unique=True; items can belong to one group at most
)
def _create_holding(stock, shares):
"""A creator function, constructs Holdings from Stock and share
quantity."""
return Holding(stock=stock, shares=shares)
class Owner(object):
def __init__(self, name):
self.name = name
holdings = association_proxy('by_stock', 'shares',
creator=_create_holding)
class Item(object):
def __init__(self, name, owner):
self.name = name
self.owner = owner
class GroupOwner(object):
def __init__(self, group, owner, item):
self.group = group
self.owner = owner
self.item = item
#assert item.owner is owner
@classmethod
def create_for_proxy(cls, owner, item):
return cls(None, owner, item)
class Group(object):
def __init__(self, items):
if items:
for item in items:
self.items_by_owner[item.owner] = item
items_by_owner = association_proxy('group_owners', 'item',
creator=GroupOwner.create_for_proxy)
mapper(Owner, owners)
mapper(Item, items, properties={
'owner': relationship(Owner),
})
mapper(Group, groups, properties={
'group_owners': relationship(GroupOwner,
collection_class=attribute_mapped_collection('owner')),
})
mapper(GroupOwner, groups_owners, properties={
'group': relationship(Group),
# Fails
'item': relationship(Item, backref=backref('group_owners',
uselist=False), single_parent=True),
# Doesn't fail
#'item': relationship(Item, backref=backref('group_owners'),
single_parent=True),
'owner': relationship(Owner),
})
meta.drop_all(bind=engine, checkfirst=True)
meta.create_all(bind=engine)
owner1 = Owner('owner 1')
item1 = Item('item 1', owner1)
owner2 = Owner('owner 2')
item2 = Item('item 2', owner2)
session.add(owner1)
session.add(owner2)
session.add(item1)
session.add(item2)
session.flush()
# Fails:
group = Group([item1, item2])
# Doesn't fail
#group = Group([item1])
session.add(group)
session.commit()
assert session.query(GroupOwner).filter_by(group_id=1, item_id=1,
owner_id=1).first() is not None
print 'Done.'
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.