Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

Relationships require the input object has a property with the same name #248

Open
multimeric opened this issue Aug 29, 2019 · 1 comment

Comments

@multimeric
Copy link

multimeric commented Aug 29, 2019

I just created a Schema with the following [simplified] definition :

class UploadSchema(Schema):
    class Meta:
        type_ = 'upload'

    id = fields.String(attribute='upload_id')
    path = fields.String()

    user = Relationship(
        related_view='rest_api.user',
        related_view_kwargs={
            'user_id': '<user_id>'
        },
        many=False,
        type_='user',
        id_field='user_id'
    )

This was based off the model definition here:

class Upload(db.Model, CRUDMixin):
    __tablename__ = "uploads"
    upload_id = Column(Integer, primary_key=True)
    path = Column(Unicode)
    user_id = Column(Integer, ForeignKey('users.user_id'))

See how, in my SQLAlchemy model, I don't have a user field? Because of the way that serialize() is defined in marshmallow (https://github.com/marshmallow-code/marshmallow/blob/e96bf97656ca3a8299d1382fae26c85f150e7e39/src/marshmallow/fields.py#L301-L306), if the get_value() call returns MISSING, the entire field is skipped, and thus the relationship is not serialized. The problem is, we don't actually need to have an underlying field for the Relationship, it's constructed using the related_kwargs argument, which in my case uses user_id, not user to find the relationship.

I suggest we add a definition for Relationship#serialize() to ensure that it still actually generates the field, even if the value for that field is MISSING.

@multimeric
Copy link
Author

multimeric commented Aug 29, 2019

In my cases, it was an easy workaround to just add an SQLAlchemy relationship() to the underlying Upload model:

class Upload(db.Model, CRUDMixin):
    __tablename__ = "uploads"
    upload_id = Column(Integer, primary_key=True)
    path = Column(Unicode)
    user_id = Column(Integer, ForeignKey('users.user_id'))

    user = relationship('User', back_populates='uploads')

But if you don't have the benefit of using an ORM that can do this, this problem would be much worse.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant