question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Combining association proxy and ordering list does not work

See original GitHub issue

Migrated issue, originally created by Wichert Akkerman (@wichert)

I want to create an ordered many-to-many relationship, where I only really care about the order from one side of the relationship. I tried to model that by creating a relationship using ordering_list, and adding an association_proxy on top of that. That works fine when adding items to the list, but fails when trying to remove items from the list.

I have attached a small python script that reproduces the error. This is the essential part of it:

class FolderImage(BaseObject):
    __tablename__ = 'folder_image'

    image_id = schema.Column(types.Integer(),
        schema.ForeignKey('image.id'), primary_key=True)
    folder_id = schema.Column(types.Integer(),
        schema.ForeignKey('folder.id'), primary_key=True)
    position = schema.Column(types.Integer())

    def __init__(self, image=None, **kw):
        BaseObject.__init__(self, image_id=image.id, **kw)


class Image(BaseObject):
    __tablename__ = 'image'
    id = schema.Column(types.Integer(), primary_key=True, autoincrement=True)


class Folder(BaseObject):
    __tablename__ = 'folder'

    id = schema.Column(types.Integer(), primary_key=True, autoincrement=True)
    _images = orm.relationship('FolderImage', order_by=[FolderImage.position],
        collection_class=ordering_list('position'))
    images = association_proxy('_images', 'image')

img = Image()
folder = Folder(images=[img])
session.add(folder)
session.flush()
folder.images = [img]
session.flush()

Running this results in:

sqlalchemy.exc.IntegrityError: (IntegrityError) NOT NULL constraint failed: folder_image.image_id u'INSERT INTO folder_image (folder_id, position) VALUES (?, ?)' (1, 0)

I am wondering if this is a regression since I apparently managed to do this a couple of years ago (see this post.


Attachments: x.py

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
sqlalchemy-botcommented, Nov 27, 2018

Michael Bayer (@zzzeek) wrote:

this has nothing to do with ordering list, take it out of the example and nothing changes…the use of assocation proxy is just wrong, plus you need a cascade delete, etc., works fine:

import sqlalchemy
from sqlalchemy import orm
from sqlalchemy import schema
from sqlalchemy import types
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.orderinglist import ordering_list


metadata = schema.MetaData()
BaseObject = declarative_base(metadata=metadata)


class FolderImage(BaseObject):
    __tablename__ = 'folder_image'

    image_id = schema.Column(types.Integer(),
        schema.ForeignKey('image.id'), primary_key=True)
    folder_id = schema.Column(types.Integer(),
        schema.ForeignKey('folder.id'), primary_key=True)
    position = schema.Column(types.Integer())

    image = orm.relationship("Image")
    folder = orm.relationship("Folder", back_populates='_images')


class Image(BaseObject):
    __tablename__ = 'image'
    id = schema.Column(types.Integer(), primary_key=True, autoincrement=True)


class Folder(BaseObject):
    __tablename__ = 'folder'

    id = schema.Column(types.Integer(), primary_key=True, autoincrement=True)
    _images = orm.relationship('FolderImage', order_by=[FolderImage.position],
        back_populates='folder',
        cascade='all, delete-orphan',
        collection_class=ordering_list('position')
        )
    images = association_proxy(
        '_images', 'image', creator=lambda img: FolderImage(image=img))


engine = sqlalchemy.create_engine('sqlite:///:memory:')
metadata.create_all(engine)
sm = orm.sessionmaker(bind=engine)

session = orm.scoped_session(sm)

img = Image()
folder = Folder(images=[img])
session.add(folder)
session.flush()
folder.images = [img]
session.flush()

0reactions
sqlalchemy-botcommented, Nov 27, 2018

Changes by Michael Bayer (@zzzeek):

  • added labels: invalid
Read more comments on GitHub >

github_iconTop Results From Across the Web

SQLAlchemy order_by many to many relationship through ...
In order to sort group.members you have to have the Persons available for sorting while loading the GroupMembership association objects.
Read more >
Association Proxy — SQLAlchemy 1.4 Documentation
Association Proxy ¶. associationproxy is used to create a read/write view of a target attribute across a relationship.
Read more >
Association Proxy - SQLAlchemy 1.1 Documentation
associationproxy is used to create a read/write view of a target attribute across a relationship. It essentially conceals the usage of a “middle”...
Read more >
Voting by Proxy Specific Rules Must Be Followed
If, on the other hand, the proxy form is drafted to designate both A and B as proxy holders, they must act jointly...
Read more >
Ordering To-Many Associations - ORM - Doctrine
To retrieve a sorted collection from the database you can use the #[OrderBy] attribute with a collection that specifies a DQL snippet that...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found