marshmallow-jsonapi tries to build self links, even if `id` is None
I have the following (simplified) schema:
class SampleFilterSchema(Schema):
class Meta:
type_ = "sample_filter"
self_view = 'rest_api.filter'
self_view_many = 'rest_api.filterlist'
self_view_kwargs = {
'sample_id': '<id>'
}
id = fields.String(attribute='sample_filter_id', allow_none=True)
tag = fields.String(attribute='sample_filter_tag')
I'm writing unit tests for my REST API, and thus I want to generate some sample data, dump it using this schema, send it in a POST request, and check that everything works. However, because I am constructing new data here, I naturally have no id for this field. This is accepted by the JSON API spec, in a request, although not a response. However, when dumping, marshmallow-jsonap still tries to construct the self links, and thus tries to use the id field (which is None), and I end up with this error:
Traceback (most recent call last):
File "/home/michael/Programming/MegaQC/tests/api/test_api.py", line 89, in test_post_resource
request = schema(many=False, exclude=['user']).dump(instance)
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 394, in format_items
return self.format_item(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 414, in get_resource_links
ret["self"] = self.generate_url(self.opts.self_url, **kwargs)
File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/marshmallow_jsonapi/flask.py", line 74, in generate_url
return flask.url_for(view_name, **kwargs) if view_name else None
File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/flask/helpers.py", line 356, in url_for
return appctx.app.handle_url_build_error(error, endpoint, values)
File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/flask/app.py", line 2061, in handle_url_build_error
reraise(exc_type, exc_value, tb)
File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/flask/helpers.py", line 345, in url_for
force_external=external)
File "/home/michael/Programming/MegaQC/venv/lib/python3.6/site-packages/werkzeug/routing.py", line 1776, in build
raise BuildError(endpoint, values, method, self)
werkzeug.routing.BuildError: Could not build url for endpoint 'rest_api.filter'. Did you forget to specify values ['filter_id']?
Is there any way to skip link generation when there is no id? Or any way to skip link generation at all? I think it would be nice to have some kind of flag that tells marshmallow that this schema is for creating a request, and so to dump a simplified version of the data, without relationships and links and IDs and such.
Here's an easy workaround:
class OptionalLinkSchema(Schema):
def __init__(self, use_links=True, *args, **kwargs):
self.use_links = use_links
super().__init__(*args, **kwargs)
def get_resource_links(self, item):
if not self.use_links:
return None
return super().get_resource_links(item)
Then you can inherit from OptionalLinkSchema, and do:
data = MySchema(use_links=False).dump(instance)
I would review/merge a PR for this. I imagine the solution will be similar to https://github.com/marshmallow-code/flask-marshmallow/pull/125/files
Excellent. I'll look into it when I get some time.