AttributeError when attaching many to many models with attributes
rpfk opened this issue · comments
Robert commented
The following example from the documentation is not working.
user.roles().attach([{1: {'attribute1': 'value1'}}, 2, 3])
When running a similar call in my project I get the following error.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\..\..\miniconda3\envs\EchoDB\lib\site-packages\orator\orm\relations\belongs_to_many.py:660: in attach
query.insert(self._create_attach_records(id, attributes))
..\..\..\miniconda3\envs\EchoDB\lib\site-packages\orator\orm\relations\belongs_to_many.py:676: in _create_attach_records
records.append(self._attacher(key, value, attributes, timed))
..\..\..\miniconda3\envs\EchoDB\lib\site-packages\orator\orm\relations\belongs_to_many.py:684: in _attacher
id, extra = self._get_attach_id(key, value, attributes)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <orator.orm.relations.belongs_to_many.BelongsToMany object at 0x0000026CFFBE3A48>
key = 1, value = {1: {'attribute1': 'value1'}}, attributes = None
def _get_attach_id(self, key, value, attributes):
"""
Get the attach record ID and extra attributes.
"""
if isinstance(value, dict):
key = list(value.keys())[0]
> attributes.update(value[key])
E AttributeError: 'NoneType' object has no attribute 'update'
..\..\..\miniconda3\envs\EchoDB\lib\site-packages\orator\orm\relations\belongs_to_many.py:699: AttributeError
The error can be solved by adding an empty dict as attributes such that the call looks like
user.roles().attach([{1: {'attribute1': 'value1'}}, 2, 3], {})
But my suggestion is to add the following to BelongsToMany.attach():
def attach(self, id, attributes=None, touch=True):
"""
Attach a model to the parent.
"""
if isinstance(id, orator.orm.Model):
id = id.get_key()
query = self.new_pivot_statement()
if not isinstance(id, list):
id = [id]
if attributes is None:
attributes = {}
query.insert(self._create_attach_records(id, attributes))
if touch:
self.touch_if_touching()