Skip to content

Deserializing a multiple nested dictionary while abiding unique constraints on foreign key tables  #455

Open
@DanielJerrehian

Description

@DanielJerrehian

I have the following SQLAlchemy Models:

class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(30), unique=True, nullable=False)
    password = db.Column(db.String(60), nullable=False)
    todos = db.relationship("ToDo", uselist=True, cascade = "all, delete", order_by="desc(ToDo.id)", backref=backref("user", uselist=False), lazy=True)
 
   
class ToDo(db.Model):
    __tablename__ = "to_do"
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    task_id = db.Column(db.Integer, db.ForeignKey('to_do_task.id'), nullable=False)
    task = db.relationship("ToDoTask", uselist=False, cascade = "all, delete", backref=backref("todos", uselist=False), lazy=True)


class ToDoTask(db.Model):
    __tablename__ = "to_do_task"
    id = db.Column(db.Integer, primary_key=True)
    task = db.Column(db.String(128), nullable=False, unique=True)

I went ahead and created the corresponding Marshmallow schemas:

class UserSchema(ma.SQLAlchemyAutoSchema):
    todos = ma.Nested("ToDoSchema", many=True)
    
    class Meta:
        model = User
        load_instance = True


class ToDoSchema(ma.SQLAlchemyAutoSchema):
    task = ma.Nested("ToDoTaskSchema", many=False)
    
    class Meta:
        model = ToDo
        load_instance = True
        include_relationships = True



class ToDoTaskSchema(ma.SQLAlchemyAutoSchema):
    to_dos = ma.Nested("ToDoSchema")

    class Meta:
        model = ToDoTask
        load_instance = True

I would ideally like to be able to add the following dictionary to the database, without adding a new task to the ToDoTask table if it already exists (hence the unique=True constraint on the model).

When trying to use the Marshmallow .load() method, I run into the error that the data cannot be added due to the unique constraint because dictionary already includes that value. I would like to only add the corresponding foreign key to the to ToDo table instead.

Given the following code:

data = {
    "email": "[email protected]",
    "password": "test",
    "todos": [
        {
            "task": {
                "task": "Gym"
            }
        }
    ]
}

user = UserSchema().load(data=data)
db.session.add(user) # Integrity error occurs here
db.session.commit()

I am getting an integrity error here because of the unique constraint on the ToDoTask.task column although I want Marshmallow to recognize the value already exists and only fetch it's ID and enter it in the ToDo table under task_id.

If the ToDoTask table contains 1 row with task equal to "Gym", I would like to populate the User table with the email="[email protected]", password="test" and then the ToDo table with user_id=2, task_id=1

Here is the link on SO if anyone is interested: https://stackoverflow.com/questions/73335484/how-to-deserialize-a-multiple-nested-dictionary-using-marshmallow-while-abiding

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions