marshmallow-jsonapi
marshmallow-jsonapi copied to clipboard
Absolute links in included relationship data
Hi, I've been struggling to make the following work:
class CommentSchema(Schema):
def __init__(self, prefix=None, *args, **kwargs):
super(CommentSchema, self).__init__(*args, **kwargs)
self.prefix = prefix
id = fields.Str()
content = fields.Str()
def get_resource_links(self, item):
return {
'self': '{} - some link'.format(self.prefix)
}
class Meta:
type_ = 'comments'
strict = True
self_url='/comments/{id}'
self_url_kwargs={'id': '<id>'}
class PostSchema(Schema):
def __init__(self, prefix, *args, **kwargs):
super(PostSchema, self).__init__(*args, **kwargs)
self.prefix = prefix
id = fields.Str(dump_only=True)
title = fields.Str()
comments = fields.Relationship(
include_resource_linkage=True,
type_='comments',
schema=CommentSchema # How to pass the prefix here?
)
class Meta:
type_ = 'posts'
strict = True
self_url = '/posts/{id}'
self_url_kwargs = { 'id': '<id>'}
Serializing a comment
This works as expected since I can pass the prefix to CommentSchema
directly.
comment = comments=Model(id=123, content='blah')
data, errors = CommentSchema('something').dump(comment) # Passing `prefix=something`
print json.dumps(data, indent=4)
The resulting dictionary contains a links
attribute with my custom links:
{
"data": {
"attributes": {
"content": "blah"
},
"type": "comments",
"id": "123",
"links": {
"self": "something - some link"
}
},
"links": {
"self": "something - some link"
}
}
Serializing a compound document
However when serializing a compound document:
comment = comments=Model(id=123, content='blah')
post = Model(id=123, title='something', comments=comment)
data, errors = PostSchema('prefix').dump(post)
print json.dumps(data, indent=4)
the resulting included
shows the links prefixed with None
:
{
"included": [
{
"attributes": {
"content": "blah"
},
"type": "comments",
"id": "123",
"links": {
"self": "None - some link"
}
}
],
"data": {
"relationships": {
"comments": {
"data": {
"type": "comments",
"id": "123"
}
}
},
"attributes": {
"title": "something"
},
"type": "posts",
"id": "123",
"links": {
"self": "/posts/123"
}
},
"links": {
"self": "/posts/123"
}
}
How can I pass extra args (prefix
) to the relationships schema=CommaSchema
option?
comments = fields.Relationship(
include_resource_linkage=True,
type_='comments',
# Invalid since `self.prefix` does not exist yet
schema=CommentSchema(self.prefix)
)
Maybe there's a better way to generate absolute links for relationship data, could you point me to an example if that's the case?
You can pass the prefix
in the schema's context attribute. The relationship field inherits the context from the parent schema which was fixed in marshmallow-jsonapi==0.19.0
.
class CommentSchema(Schema):
id = fields.Str()
content = fields.Str()
def get_resource_links(self, item):
prefix = self.context['prefix']
return {
'self': '{} - comment link'.format(prefix)
}
class Meta:
type_ = 'comments'
strict = True
self_url = '/comments/{id}'
self_url_kwargs = {'id': '<id>'}
class PostSchema(Schema):
id = fields.Str(dump_only=True)
title = fields.Str()
comments = fields.Relationship(
include_resource_linkage=True,
type_='comments',
schema=CommentSchema # How to pass the prefix here?
)
def get_resource_links(self, item):
prefix = self.context['prefix']
return {
'self': '{} - post link'.format(prefix)
}
class Meta:
type_ = 'posts'
strict = True
self_url = '/posts/{id}'
self_url_kwargs = {'id': '<id>'}
comments = {'id': 123, 'content': 'blah'}
post = {'id': 123, 'title': 'something', 'comments': comments}
data = PostSchema(context={'prefix': 'prefix'}, include_data=('comments',)).dump(post)
print(json.dumps(data, indent=4))
{
"data": {
"type": "posts",
"relationships": {
"comments": {
"data": {
"type": "comments",
"id": "123"
}
}
},
"id": "123",
"attributes": {
"title": "something"
},
"links": {
"self": "prefix - post link"
}
},
"links": {
"self": "prefix - post link"
},
"included": [
{
"type": "comments",
"attributes": {
"content": "blah"
},
"id": "123",
"links": {
"self": "prefix - comment link"
}
}
]
}