Skip to content

Commit

Permalink
Merge pull request #12 from paulcwatts/write-only-fields
Browse files Browse the repository at this point in the history
Fix write_only fields
  • Loading branch information
paulcwatts authored Dec 11, 2017
2 parents 1318a9b + d5b7153 commit f1e6b95
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
7 changes: 5 additions & 2 deletions rest_framework_json_schema/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ def render(self, data, context):
def render_attributes(self, data, context):
attributes = self.filter_by_fields(self.attributes, context.fields)
return OrderedDict(
(self.transformed_names[attr], self.from_data(data, attr)) for attr in attributes
(self.transformed_names[attr], self.from_data(data, attr))
for attr in attributes if attr in data
)

def render_relationships(self, data, context):
Expand All @@ -132,6 +133,8 @@ def render_relationships(self, data, context):
raise IncludeInvalid('Invalid relationship to include: %s' % key)

filtered = self.filter_by_fields(self.relationships, context.fields, lambda x: x[0])
# Filter by missing values in the data
filtered = (rel for rel in filtered if rel[0] in data)
for (name, rel) in filtered:
relationship, rel_included = self.render_relationship(data, name, rel, context)
relationships[self.transformed_names[name]] = relationship
Expand Down Expand Up @@ -165,7 +168,7 @@ def filter_by_fields(self, names, fields, name_fn=lambda name: name):
type_fields = fields[self.type]
# This is essentially an intersection, but we preserve the order
# of the attributes/relationships specified by the schema.
return [name for name in names if self.transformed_names[name_fn(name)] in type_fields]
return (name for name in names if self.transformed_names[name_fn(name)] in type_fields)


class ResourceIdObject(BaseLinkedObject):
Expand Down
40 changes: 40 additions & 0 deletions rest_framework_json_schema/tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,46 @@ class AlbumObject(ResourceObject):
)))
self.assertEqual(included, [])

def test_tolerate_missing_attributes(self):
"""
To support write_only data, be tolerant if an attribute isn't in the data.
"""
obj = ResourceObject(id='user_id', type='users', attributes=('first_name', 'last_name'))
primary, included = obj.render({
'user_id': '123',
'first_name': 'John'
}, Context(self.request))
self.assertEqual(primary, OrderedDict((
('id', '123'),
('type', 'users'),
('attributes', OrderedDict((('first_name', 'John'),)))
)))
self.assertEqual(included, [])

def test_tolerate_missing_relationships(self):
"""
To support write_only data, be tolerant if a relationship isn't in the data.
"""
class AlbumObject(ResourceObject):
type = 'album'
relationships = ('artist', 'artist2')

# Empty to-one relationship: relationship is 'None'
# Empty to-many relationship: relationship is '[]'
# Single relationship: a ResourceIdObject
# To-Many: an array of ResourceIdObjects
obj = AlbumObject()

primary, included = obj.render({'id': '123', 'artist2': None}, Context(self.request))
self.assertEqual(primary, OrderedDict((
('id', '123'),
('type', 'album'),
('relationships', OrderedDict((
('artist2', OrderedDict((('data', None),))),
)))
)))
self.assertEqual(included, [])

def test_render_included(self):
"""
You can render included resources
Expand Down

0 comments on commit f1e6b95

Please sign in to comment.