collective / collective/collective.exportimport

Exporting portlet with relation field fails

Open
#47 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
19
Forks
20
PR merge metrics
No merged PRs in 30d

Description

I have several relation fields in a portlet. Exporting portlets then fails because a `RelationValue` is not json serialisable:

```
http://localhost:9152/plone/@@export_portlets
Traceback (innermost last):
Module ZPublisher.Publish, line 138, in publish
Module ZPublisher.mapply, line 77, in mapply
Module ZPublisher.Publish, line 48, in call_object
Module collective.exportimport.export_other, line 477, in __call__
Module json, line 251, in dumps
Module json.encoder, line 209, in encode
Module json.encoder, line 431, in _iterencode
Module json.encoder, line 332, in _iterencode_list
Module json.encoder, line 408, in _iterencode_dict
Module json.encoder, line 408, in _iterencode_dict
Module json.encoder, line 332, in _iterencode_list
Module json.encoder, line 408, in _iterencode_dict
Module json.encoder, line 408, in _iterencode_dict
Module json.encoder, line 442, in _iterencode
Module json.encoder, line 184, in default
TypeError: is not JSON serializable
```

A bit related Is [this comment](https://github.com/collective/collective.exportimport/pull/33#issuecomment-883935512) from Philip where he removes some relations code, although I guess this was only active when exporting content, and not portlets.

The following diff in the portlet export code fixes it for me:

```
$ git diff
diff --git a/src/collective/exportimport/export_other.py b/src/collective/exportimport/export_other.py
index f358a1c..383635a 100644
--- a/src/collective/exportimport/export_other.py
+++ b/src/collective/exportimport/export_other.py
@@ -535,13 +535,18 @@ def export_local_portlets(obj):
settings = IPortletAssignmentSettings(assignment)
if manager_name not in items:
items[manager_name] = []
+ from z3c.relationfield.relation import RelationValue
+ assignment_data = {}
+ for name in schema.names():
+ value = getattr(assignment, name, None)
+ if value and isinstance(value, RelationValue):
+ value = value.to_object.UID()
+ assignment_data[name] = value
+
items[manager_name].append({
'type': portlet_type,
'visible': settings.get('visible', True),
- 'assignment': {
- name: getattr(assignment, name, None)
- for name in schema.names()
- },
+ 'assignment': assignment_data,
})
return items
```

The code needs to be more robust, but those are details.
I am not sure if this is a reasonable place for this fix or if there is a more general place.

Ah, wait, using this works too:

```
json_compatible(getattr(assignment, name, None))
```

At least then you get an export without errors, although my earlier code that returns uuids could be preferable in some cases.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in src/collective/exportimport/export_other.py at export_local_portlets and inspect how assignment values are assembled before json.dumps. Compare the reported RelationValue handling with json_compatible; done means exporting portlets containing relation fields completes without a serialization error and preserves the intended relation representation.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.