[adapters] Use an adapter for serializing entities to a bare python structure
which may be used for e.g. JSON export or other and allow to have different
serializations for each entity types.
Closes #6378035
--- a/entities/adapters.py Tue Dec 08 16:28:20 2015 +0100
+++ b/entities/adapters.py Tue Dec 15 08:55:58 2015 +0100
@@ -349,6 +349,32 @@
return path
+class ISerializableAdapter(view.EntityAdapter):
+ """Adapter to serialize an entity to a bare python structure that may be
+ directly serialized to e.g. JSON.
+ """
+
+ __regid__ = 'ISerializable'
+ __select__ = is_instance('Any')
+
+ def serialize(self):
+ entity = self.entity
+ entity.complete()
+ data = {
+ 'cw_etype': entity.cw_etype,
+ 'cw_source': entity.cw_metainformation()['source']['uri'],
+ }
+ for rschema, __ in entity.e_schema.attribute_definitions():
+ attr = rschema.type
+ try:
+ value = entity.cw_attr_cache[attr]
+ except KeyError:
+ # Bytes
+ continue
+ data[attr] = value
+ return data
+
+
# error handling adapters ######################################################
from cubicweb import UniqueTogetherError
--- a/entities/test/unittest_base.py Tue Dec 08 16:28:20 2015 +0100
+++ b/entities/test/unittest_base.py Tue Dec 15 08:55:58 2015 +0100
@@ -232,5 +232,24 @@
eclass = self.select_eclass('Division')
self.assertEqual(eclass.cw_etype, 'Division')
+
+class ISerializableTC(CubicWebTC):
+
+ def test_serialization(self):
+ with self.admin_access.repo_cnx() as cnx:
+ entity = cnx.create_entity('CWGroup', name=u'tmp')
+ cnx.commit()
+ serializer = entity.cw_adapt_to('ISerializable')
+ expected = {
+ 'cw_etype': u'CWGroup',
+ 'cw_source': 'system',
+ 'cwuri': u'http://testing.fr/cubicweb/%s' % entity.eid,
+ 'creation_date': entity.creation_date,
+ 'modification_date': entity.modification_date,
+ 'name': u'tmp',
+ }
+ self.assertEqual(serializer.serialize(), expected)
+
+
if __name__ == '__main__':
unittest_main()
--- a/web/views/json.py Tue Dec 08 16:28:20 2015 +0100
+++ b/web/views/json.py Tue Dec 15 08:55:58 2015 +0100
@@ -106,7 +106,8 @@
The following additional metadata is added to each row :
- - ``__cwetype__`` : entity type
+ - ``cw_etype`` : entity type
+ - ``cw_source`` : source url
"""
__regid__ = 'ejsonexport'
__select__ = EntityView.__select__ | empty_rset()
@@ -115,12 +116,8 @@
def call(self):
entities = []
for entity in self.cw_rset.entities():
- entity.complete() # fetch all attributes
- # hack to add extra metadata
- entity.cw_attr_cache.update({
- '__cwetype__': entity.cw_etype,
- })
- entities.append(entity)
+ serializer = entity.cw_adapt_to('ISerializable')
+ entities.append(serializer.serialize())
self.wdata(entities)