How to modify values of many to many relationship in the crud interface
See original GitHub issueFirst check
- I added a very descriptive title to this issue.
- I used the GitHub search to find a similar issue and didn’t find it.
- I searched the FastAPI documentation, with the integrated search.
- I already searched in Google “How to X in FastAPI” and didn’t find any information.
- I already read and followed all the tutorial in the docs and didn’t find an answer.
- I already checked if it is not related to FastAPI but to Pydantic.
- I already checked if it is not related to FastAPI but to Swagger UI.
- I already checked if it is not related to FastAPI but to ReDoc.
- After submitting this, I commit to one of:
- Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
- I already hit the “watch” button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
- Implement a Pull Request for a confirmed bug.
Hello everyone. I am having a really hard time updating a user with a many to many relationship. The models used are these.
class UserBase(BaseModel):
email: Optional[EmailStr] = None
is_active: Optional[bool] = True
is_superuser: bool = False
full_name: Optional[str] = None
roles: List[Role] = []
class User(Base):
id = Column(Integer, primary_key=True, index=True)
full_name = Column(String, index=True)
email = Column(String, unique=True, index=True, nullable=False)
hashed_password = Column(String, nullable=False)
is_active = Column(Boolean(), default=True)
is_superuser = Column(Boolean(), default=False)
items = relationship("Item", back_populates="owner")
roles = relationship(
'Role', secondary=user_role,
backref=backref("users")
)
All the models have Config orm=True
The usage is that I have an admin panel where I can add roles to a profile. So I get the json model to the Vue app, add new roles and then post it to the api. When this updated model tries to set the roles attribute it fails.
Now after the endpoint is called. I see the new roles in the pydantic model as expected. But when the crud update tries to apply the new roles in the list it fails.
But when it reaches this point
def update(
self,
db: Session,
*,
db_obj: ModelType,
obj_in: Union[UpdateSchemaType, Dict[str, Any]]
) -> ModelType:
obj_data = jsonable_encoder(db_obj)
if isinstance(obj_in, dict):
update_data = obj_in
else:
update_data = obj_in.dict(exclude_unset=True)
for field in obj_data:
if field in update_data:
setattr(db_obj, field, update_data[field]) <------- Fails here
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
When I try to update user profile and add more roles to the list. I get the following error. backend_1 | File “/usr/local/lib/python3.8/site-packages/sqlalchemy/orm/unitofwork.py”, line 45, in append backend_1 | item_state = attributes.instance_state(item) backend_1 | AttributeError: ‘dict’ object has no attribute ‘_sa_instance_state’
Any idea what I can be doing incorrectly ? Using fastapi = “^0.60.1” and Python 3.8 Thanks
Issue Analytics
- State:
- Created 3 years ago
- Comments:6
Top GitHub Comments
Hi,
after looking at SQLAlchemy I realized that for having many to many relations like
user_role
we should do something like below code:don’t forget to import UserRole class in User and Role classes
the problem is that
jsonable_encoder
returns an empty object{}
when called on a model that contains a many-to-many relationship, thus you cannot use inherited functions fromcrud/base.py