Skip to content

Support for associationproxy #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rafmagns-skepa-dreag opened this issue Jun 15, 2018 · 7 comments · Fixed by #267
Closed

Support for associationproxy #136

rafmagns-skepa-dreag opened this issue Jun 15, 2018 · 7 comments · Fixed by #267
Assignees
Milestone

Comments

@rafmagns-skepa-dreag
Copy link

Hi,

I'm using graphene-sqlalchemy 2.0.0. I haven't found any documentation around association proxy support and my preliminary efforts into finding it in the code/docs/issues have proved futile. Are association proxies supported? If not, is there a plan to support them?

Thanks!

@mekhami
Copy link

mekhami commented Jun 28, 2018

Seconding this, an initial google search came up dry and I'm wondering how to access related models via the association proxy.

@oj-lappi
Copy link

This is important to me as well. Feels like a core feature that should be present.

@ghost
Copy link

ghost commented Jan 10, 2019

Does anyone have a workaround for accessing AssociationProxy fields?

Edit: I gave AssociationProxy models their own nodes and linked the associated objects via one to one relationships.

@mirceaciu
Copy link

mirceaciu commented Nov 21, 2019

Myself got at least part of it to work. I have Playlists and Media models, both many-to-many in both directions (one playlist can have many media, one media can be part of many playlists)

class Playlist(Base):
    __tablename__ = 'playlists'

    id = Column(BigInteger, primary_key=True)
    #other fields here    

    media = association_proxy('media_associations', 'media')
class Media(Base):
    __tablename__ = 'media'

    id = Column(BigInteger, primary_key=True)
    uid = Column(String(50), unique=True, index=True, nullable=False)

    #other fields here    

    playlists = association_proxy('playlist_associations', 'playlist')

These two models are tied together via the association_proxy and

class PlaylistsMedia(Base):
    __tablename__ = 'playlists_media'
    id = Column(BigInteger, primary_key=True)

    playlist_id = Column(BigInteger, ForeignKey('playlists.id'))
    media_uid = Column(String, ForeignKey('media.uid'))

    playlist = relationship(
        'Playlist',
        backref=backref("media_associations", cascade="all, delete-orphan"),
        lazy='subquery'
    )
    media = relationship(
        'Media',
        backref=backref("playlist_associations", cascade="all, delete-orphan"),
        lazy='subquery'
    )

    def __init__(self, playlist=None, media=None):
        self.playlist = playlist
        self.media = media

More details here, my implementation allows to have multiple "media" in one playlists.

On the Graph side

class PlaylistNode(SQLAlchemyObjectType):
    class Meta:
        model = Playlist
        interfaces = (graphene.relay.Node, )

    uid = graphene.String(description='Playlist uid generated at creation')
    name = graphene.String(description='Playlist name as set by user')
    # other fields here

    media = graphene.List(MediaNode, description='collection of media associated to this playlist')

That's the Node for my Playlists model. Notice media, that will allow access to the associated media field I set in the model.

class Query(graphene.ObjectType):
    """Query objects for GraphQL API."""
    class Meta:
        interfaces = (graphene.relay.Node,)
    node = graphene.relay.Node.Field()
    viewer = graphene.Field(Viewer)

    paginate_playlists = graphene.Field(lambda: graphene.List(PlaylistNode),
                                      page=graphene.Int(required=True),
                                      per_page=graphene.Int(required=True),
                                      order_by=graphene.Int(required=True),
                                      )
    @staticmethod
    def resolve_paginate_screens(root, info, **kwargs):
        # here I query the Playlists model and return the items

Accessing that query from frontend with

query paginatePlaylists($page:Int!, $perPage: Int!, $orderBy: Int!){
  paginatePlaylists(page:$page, perPage:$perPage, orderBy:$orderBy){
    uid
    name
    status
    dateCreated
    scheduled
    scheduleStart
    scheduleStop
    onPage
    pagesCount
    media{
      id
      uid
      anyOtherFieldFromTheMediaNode
    }
  }
}

With all that I am able to query media associated to this playlist.

It would be nice to do the same the other way around but I can't add the PlaylistNode as a graphene.List to my MediaNode because scope logic:

  • to add MediaNode in PlaylistNode I first need to create MediaNode and then PlaylistNode. Media can be added to Playlist but Playlist can't be added to Media (it was not yet defined). In SQLAlchemy I can use model names as string and not be limited by the fact that the Class was not yet defined
users_screens_association = Table('users_screens', Base.metadata,
    Column('user_id', BigInteger, ForeignKey('users.id')),
    Column('screen_id', String, ForeignKey('screens.device_id'))
)

@mirceaciu
Copy link

mirceaciu commented Nov 21, 2019

Does anyone have a workaround for accessing AssociationProxy fields?

Edit: I gave AssociationProxy models their own nodes and linked the associated objects via one to one relationships.

ghost I just understood what you suggested there.

I can create as many nodes as I need from my Media and Playlist models. I can define and use them anywhere I need, and that's what I did and now I have a working Graph for my bidirectional many-to-many association-proxy relationship :D

@erikwrede
Copy link
Member

#267 should solve this issue and will be merged soon!

@erikwrede erikwrede self-assigned this May 14, 2022
@erikwrede erikwrede added this to the 3.0 milestone May 14, 2022
Copy link

github-actions bot commented Apr 4, 2024

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related topics referencing this issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants