Request association table attribute (SQLAlchemy) from Strawberry (GraphQL)

35 Views Asked by At

I have two db models 'Lab' (list of the labs) and 'File' (list of the uploaded files). I had to create a an association table which shows One-To-Many relationship between them 'LabFile'.

Everything works fine, but I am not able to return file_id (file.id), file_path (file.path) and file_type (lab_file.file_type) all at the same time after Lab creation through GraphQL API. There is no issue returning only file_id (file.id) and file_path (file.path). However, I can not access association table's attribute.

I do not want to introduce the resolver. Hopefully there is an easier way of getting association table attributes along with the main relationship table attributes.

Can you please have a look on db models & GraphQL APIs and suggest what I must change to get all of the fields I need.

DB models

class Lab(BaseDataModel):
    __tablename__ = 'labs'

    id: UUID = Column(GUID, default=uuid4, primary_key=True)
    title: str = Column(String(255), nullable=False)
    description: str = Column(Text)
    files: list['File'] = relationship('File', secondary='lab_files', back_populates='lab')

class LabFile(FileAssociationBase):
    __tablename__ = 'lab_files'

    lab_id: UUID = Column(GUID, ForeignKey('labs.id', ondelete='CASCADE'), nullable=False, index=True)

class FileType(str, Enum):
    ICON = 'ICON'
    ATTACHMENT = 'ATTACHMENT'

class FileAssociationBase(BaseDataModel):
    """
    File Association base class that includes common attributes for file associations
    """

    __abstract__ = True

    id = Column(Integer, primary_key=True)

    @declared_attr
    def file_id(cls):
        return Column(GUID, ForeignKey('files.id', ondelete='CASCADE'), nullable=False)

    file_type = Column(ENUM(FileType), nullable=False)

    @declared_attr
    def __table_args__(cls):
        return (UniqueConstraint('file_id', name=f'uq__{cls.__tablename__}__file_id'),)

class File(BaseDataModel):

    __tablename__ = 'files'

    id: UUID = Column(GUID, primary_key=True)
    path = Column(String(255), nullable=False)

    lab: 'Lab' = relationship('Lab', secondary='lab_files', back_populates='files')

GraphQL

@strawberry.input
class LabCreateInput:
    title: str
    description: str | None = strawberry.UNSET
    files: list[FileInput] | None = strawberry.UNSET

@strawberry.type
class LabReadOutput(BaseGQLModel):
    id: UUID
    title: str
    description: str | None
    files: list[FileReadOutput]

@strawberry.enum
class FileType(str, Enum):
    ICON = 'ICON'
    ATTACHMENT = 'ATTACHMENT'

@strawberry.input
class FileInput:
    file_id: UUID
    file_type: FileType

@strawberry.type
class FileReadOutput:
    id: UUID
    path: str
    file_type: FileType
1

There are 1 best solutions below

1
Moon On

Try to remove "secondary" option from the relationship, you will get lab_files attributes as well as files attributes