PynamoDB
PynamoDB copied to clipboard
why do I have an empty attribute_values field in my DynamicMapAttribute attribute
Hello,
I have an attribute setup with way:
class MediaMap(MapAttribute):
ct = NumberAttribute(default_for_new=0)
items = DynamicMapAttribute(default_for_new=dict)
class MediaGroupMap(MapAttribute):
docs = MediaMap(default_for_new=dict)
files = MediaMap(default_for_new=dict)
audios = MediaMap(default_for_new=dict)
images = MediaMap(default_for_new=dict)
videos = MediaMap(default_for_new=dict)
When I insert data and pull it back out I get an empty attribute_values
map. Is it by design?
"media":{
"audios":{
"ct":1,
"items":{
"attribute_values":{
},
"2021_11_18T09_22_11_071586_a72a8227_64f3_4bcf_9e27_0c127d71feaa":{
"execution_id":"2eef13d2-a8ab-4837-84fe-56ccc3593cdf",
"media_size":443926,
"content_type":"application/octet-stream",
"etag":"2ca80224c6de3f27c3db8ebc8a7444b3",
"source":"upload",
"media_group":"audios"
}
}
},
"docs":{
"ct":1,
"items":{
"attribute_values":{
},
"2021_11_18T09_22_11_267344_a45b4a73_9f9e_40fa_949f_8bd54ff83fa5":{
"execution_id":"b7b37d90-9252-441c-af1f-ec626bcd5564",
"media_size":32768,
"content_type":"application/octet-stream",
"etag":"50f723d62aa1ff16cfbe5af1e93b7008",
"source":"upload",
"media_group":"docs"
}
}
},
"files":{
"ct":1,
"items":{
"attribute_values":{
},
"2021_11_18T09_22_11_467357_40dce364_7efc_4a62_8a5b_5264d141126f":{
"execution_id":"e6441017-2ad3-4807-ad0f-9c72de5421ca",
"media_size":8,
"content_type":"application/octet-stream",,
"etag":"eb1a3227cdc3fedbaec2fe38bf6c044a",
"source":"upload",
"media_group":"files"
}
}
},
"images":{
"ct":1,
"items":{
"attribute_values":{
},
"2021_11_18T09_22_11_590072_4168e196_bd79_4a58_b47a_a059408abe9e":{
"execution_id":"c59cb061-8107-401e-8bb5-c9de546f93de",
"media_size":350749,
"content_type":"application/octet-stream",
"etag":"5297bd123ad4ddad723483c176e35f6e",
"source":"upload",
"media_group":"images"
}
}
},
"videos":{
"ct":1,
"items":{
"attribute_values":{
},
"2021_11_18T09_22_11_846882_88b55dc6_0508_4a76_9176_6f6c11349495":{
"execution_id":"550ce829-f643-4fe0-8742-2b6d53e50cfc",
"media_size":1055736,
"content_type":"application/octet-stream",
"etag":"d55bddf8d62910879ed9f605522149a8",
"source":"upload",
"media_group":"videos"
}
}
}
}
Thank you so much in advance
This is a problem for me too. I wanted to upgrade my PynamoDB version and start using DynamicMapAttribute, but several tests of mines are failing because of this behavior and I can't move forward.
The only thing I can add about this behavior is that it only happens with the update operations. The save() does not do had the attribute_values
in the DynamicMapAttribute.
+1 same for me
I did some investigation and found what is happening.
Basically, when we deserialize the object, the method _container_deserialize
gets called. The issue is that inside that function, it sets self.attribute_values = {}
to initialize it. Normally this works fine, but on MapAttribute
, it calls __setattr__
, which instead of "self.attribute_values = {}
" does self.attribute_values["attribute_values"] = {}
.
Going of the comment in __setattr__
:
# "Raw" (i.e. non-subclassed) instances set their name-value pairs in the `attribute_values` dictionary.
# MapAttribute subclasses should set attributes via the Attribute descriptors.
if self.is_raw() and self._is_attribute_container():
self.attribute_values[name] = value
...
I think the issue is in the implementation of the is_raw
method.
On MapAttribute
it looks like this:
@classmethod
def is_raw(cls):
return cls == MapAttribute
But on DynamicMapAttribute
it looks like this this:
@classmethod
def is_raw(cls):
# All subclasses of DynamicMapAttribute should be treated like "raw" map attributes.
return True
Hope this helps.
I also took some time to look into this and found the same issue as @fdobrovolny. I also found a fix that treats the "attribute_values" attribute as a special case in the __setattr__
method. However, technically it may break backwards-compatibility if anyone actually wants an attribute called "attribute_values". To be honest, I don't really see a way around this, though.
So it's not just me who gets this.
I have a use case where I keep a map of maps like so:
"myMap": {
"aba75878-c068-4f64-8559-ea62706b9c11": {
"foo": "bar",
"bar": "foo"
},
"eb6009b4-883e-46b9-a066-151e88f7c7d4": {
"foo": "bar",
"bar": "foo"
},
}
Basically a list of maps, but using a Map instead of a list. I could define each item with a MapAttribute
but my key names are just generated strings, so I'd need to use the DynamicMapAttribute
but that keeps adding this attribute_values
key, which is breaking my app.
Any idea what I could use to get around this?