With marshmallow@3.11.1, Flask@1.1.2, Flask-SQLAlchemy@2.4.4 and SQLAlchemy@1.3.23 I am trying to store a new data in DB.
I do not have any issues creating records without any relations on with one-to-many relations, but I am struggling to create a new record with a many-to-many relations.
I have Positions, which may have different Types. To have a many-to-many relation I use an associated table:
class PositionsModel(db.Model):
__tablename__ = "positions"
id = db.Column(db.Integer, primary_key=True)
position_name = db.Column(db.String(150), nullable=False)
types_of_work = db.relationship(
"TypesOfWorkModel",
secondary=positions_types_of_work,
lazy="joined",
backref=db.backref("type_positions", lazy="noload")
)
def __init__(self, data):
self.position_name = data.get("position_name")
self.types_of_work = data.get("types_of_work", [])
def create(self):
db.session.add(self)
db.session.commit()
class TypesOfWorkModel(db.Model):
__tablename__ = "types_of_work"
id = db.Column(db.Integer, primary_key=True)
work_type_name = db.Column(db.String(150), nullable=False)
positions_types_of_work = db.Table(
"positions_types_of_work",
db.Column("position_id", db.Integer, db.ForeignKey("positions.id"), primary_key=True),
db.Column("type_of_work_id", db.Integer,
db.ForeignKey("types_of_work.id"), primary_key=True)
)
I also have a schema for every other table, which I am using when creating records. Here is my schema for creating a new Position:
class PositionsModelSchemaCreate(Schema):
id = fields.Int()
position_name = fields.Str(required=True)
types_of_work = fields.List(
fields.Int,
validate=validate_types_of_work
)
@post_load
def attach_models(self, data, **kwargs):
# query to get actual model records for "types_of_work"
return data
So what happens when a request comes to create a new position?
"""
request data looks like this:
{
"position_name": "Test",
"types_of_work": [1, 2]
}
"""
req_data = request.get_json()
data = positions_schema_create.load(req_data)
This piece of code loads data according to the schema, calls validation functions. In types_of_work case it just checks in the IDs in the request body are the IDs of the existing records in the DB.
Then it reaches @post_load decorator, which substitutes the IDs for types_of_work to actual DB records of those types.
Eventually, my request data will look like this:
{
'position_name': 'Pos Name Test',
'types_of_work': [<TypesOfWork One>, <TypesOfWork Two>]
}
Which I am using for creation:
position = PositionsModel(data)
position.create()
And it returns me an error:
int() argument must be a string, a bytes-like object or a number, not 'TypesOfWorkModel'
I read a few other posts here and here and looks like I am doing everything accordingly, but still have an error.
Any advice would be greatly appreciated!