Skip to content
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

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 join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant