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

self links are constructed using the dumped data, not the original input #247

Open
multimeric opened this issue Aug 26, 2019 · 5 comments
Open

Comments

@multimeric
Copy link

multimeric commented Aug 26, 2019

I have the following schema:

from marshmallow_jsonapi.flask import Schema

class SampleDataSchema(Schema):
    class Meta:
        type_ = 'sample_data'
        self_view = 'rest_api.sampledata'
        self_view_many = 'rest_api.sampledata'
        self_view_kwargs = {
            'sample_id': '<sample_id>'
        }

    id = fields.Integer(attribute='sample_data_id')
    value = fields.String()
    # These methods have been removed since they're irrelevant to my issue
    key = ma.Method('type_key')
    section = ma.Method('type_section')

A model:

class SampleData(db.Model, CRUDMixin):
    __tablename__ = "sample_data"
    sample_data_id = Column(Integer, primary_key=True)
    sample_id = Column(Integer, ForeignKey('sample.sample_id', ondelete='CASCADE'), index=True, nullable=False)
    value = Column(Unicode)
    sample = relationship('Sample', back_populates='data')

And a view function:

    def get(self, sample_id):
        samples = db.session.query(
            models.SampleData
        ).options(
            joinedload(models.SampleData.data_type)
        ).filter(
            models.SampleData.sample_id == sample_id
        ).all()
        return schemas.SampleDataSchema(many=True).dump(samples)

However, when I hit the view endpoint, I get this error:

  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow/schema.py", line 545, in dump
    POST_DUMP, result, many=many, original_data=obj
  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow/schema.py", line 993, in _invoke_dump_processors
    tag, pass_many=True, data=data, many=many, original_data=original_data
  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow/schema.py", line 1122, in _invoke_processors
    data = processor(data, many=many, **kwargs)
  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow_jsonapi/schema.py", line 135, in format_json_api_response
    ret = self.format_items(data, many)
  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow_jsonapi/schema.py", line 392, in format_items
    return [self.format_item(item) for item in data]
  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow_jsonapi/schema.py", line 392, in <listcomp>
    return [self.format_item(item) for item in data]
  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow_jsonapi/schema.py", line 381, in format_item
    links = self.get_resource_links(item)
  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow_jsonapi/schema.py", line 413, in get_resource_links
    kwargs = resolve_params(item, self.opts.self_url_kwargs or {})
  File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow_jsonapi/utils.py", line 58, in resolve_params
    "attribute of {obj!r}".format(attr_name=attr_name, obj=obj)
AttributeError: 'sample_id' is not a valid attribute of {'value': '20.fastq', 'id': 501, 'key': 'fastqc__Filename', 'section': 'fastqc'}

So, from the last line it's obvious that marshmallow-jsonapi is trying to pull the field sample_id from the dumped data, since it has an id field, which was not on the original model. However, this makes very little sense to me. We often want to generate a link using the model, but not to include the foreign key in the final data. Shouldn't we generate the self links using the original record, like we do for relationship links?

@multimeric
Copy link
Author

Note: this is the same error as #224

@multimeric
Copy link
Author

multimeric commented Aug 26, 2019

We could do this by generating the link objects in a @pre_dump method, and then attaching the links to the result in a @post_dump, whereas both are currently done in a @post_dump.

@sloria
Copy link
Member

sloria commented Sep 5, 2019

@TMiguelT Thanks for reporting all these issues and your workarounds. Unfortunately, I don't have much time to look into these, as I'm not using this project at work, and I'm busy with core marshmallow development in my free time. Feel free to send PRs; I can merge and release them as they come.

@multimeric
Copy link
Author

That's fine, I totally understand. I'm just putting them here so that they're better documented so I or someone else can solve them down the track. And the workarounds might help people in the meantime. Please don't feel like I'm demanding that they be fixed or anything.

@multimeric
Copy link
Author

Incidentally, I think the best way to solve this would be to make format_json_api_response use @post_dump(pass_original=True), which is a flag I didn't know about when I first made this issue.

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

2 participants