-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
hybrid properties with custom setter not supported #345
Comments
I ran into the same issue. I solved this by using a pre load hook to do the logic on the schema instead of the ORM. Not ideal ofc but it works. I just copied the custom setter code over since it's only one line for me, but you could probably call the method specifically to keep it DRY.
|
By explicitly setting the from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, auto_field
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
base = declarative_base()
#define our Model
class User(base):
__tablename__ = "users"
id = Column(Integer, autoincrement=True, primary_key=True)
username = Column(String(100), nullable=False)
_password = Column(String(100), nullable=False)
@hybrid_property
def password(self):
return self._password
@password.setter
def password(self, plaintext):
self._password = hash(plaintext)
# create the AutoSchema
class UserSchema(SQLAlchemyAutoSchema):
class Meta(object):
model = User
load_instance = True
transient = True
ordered = True
_password = auto_field(data_key="password", attribute="password")
# test serialize
u = User(id=1337, username="admin", password="admin")
assert u.id == 1337
assert u.username == "admin"
assert u.password != "admin" # its not admin, bc. the custom setter was called and the password was hashed
assert UserSchema(exclude=["_password"]).dump(u) == {
"id": 1337,
"username": "admin",
}
# test deserialize
u2: User = UserSchema().load({
"id": 1337,
"password": "admin", # gives exception bc the _password field isnt set
"username": "admin",
})
assert u2.password != "admin" Here's the diff: diff --git a/orig.py b/main.py
index 7d9986e..babfa6b 100644
--- a/orig.py
+++ b/main.py
@@ -1,4 +1,4 @@
-from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
+from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, auto_field
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
@@ -30,6 +30,8 @@ class UserSchema(SQLAlchemyAutoSchema):
transient = True
ordered = True
+ _password = auto_field(data_key="password", attribute="password")
+
# test serialize
u = User(id=1337, username="admin", password="admin") |
Hey, it seems custom hybrid property setters arent called when deserializing data:
the problem is here:
what did i do wrong? Or is my understanding wrong? i would except the following:
this should set the underlying prop directly (bypassing the hybrid property+setter, and this should work too:
this should call the the custom setter for password and write hashed value to the underlying
_password
property.any ideas on how to achieve this?
The text was updated successfully, but these errors were encountered: