sjm*_*jmh 5 sqlalchemy flask marshmallow
我正在尝试使用flask-rest-api作为一个简单的示例webservice的框架,SQLAlchemy作为ORM。一切正常,除非处理更新。
这是有问题的代码:
@blp.arguments(DogSchema)
@blp.response(DogSchema)
def put(self, data, dog_id):
"""Update existing dog"""
try:
dog = Dog.query.get(dog_id)
except Exception as e:
abort(404, message="Item not found - %s" % e)
# update the dog here
return dog
Run Code Online (Sandbox Code Playgroud)
当它执行时,data变量是一个瞬态狗模型对象。flask-rest-api 负责对 JSON 请求中的数据进行反序列化,查看您的 Marshmallow 模式并创建正确类型的 sqlalchemy 模型对象。
为了完整起见,这是我的模型和模式:
class Dog(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String, nullable=False)
@api.definition("Dog")
class DogSchema(ma.ModelSchema):
class Meta:
model = Dog
strict = True
ordered = True
id = field_for(Dog, 'id', dump_only=True)
Run Code Online (Sandbox Code Playgroud)
我想要做的只是获取瞬态对象并使用所有属性更新会话中的对象。
我已经能够以两种不同的方式做到这一点,我都不喜欢这两种方式,我希望有更好的方法来做到这一点。
@blp.arguments(DogSchema)
@blp.response(DogSchema)
def put(self, data, dog_id):
"""Update existing dog"""
try:
dog = Dog.query.get(dog_id)
except Exception as e:
abort(404, message="Item not found - %s" % e)
data.id = dog_id
db.session.merge(data)
db.session.commit()
return dog
Run Code Online (Sandbox Code Playgroud)
这有效,但合并似乎有其他副作用 - 如果记录不在会话中,它会从数据库中提取,如果它不存在于数据库中,则添加它。
@blp.arguments(DogSchema)
@blp.response(DogSchema)
def put(self, data, dog_id):
"""Update existing dog"""
try:
dog = Dog.query.get(dog_id)
except Exception as e:
abort(404, message="Item not found - %s" % e)
serializer = DogSchema()
serializer.load(serializer.dump(data).data, instance=dog, session=db.session, partial=True)
db.session.commit()
return dog
Run Code Online (Sandbox Code Playgroud)
这使用 Marshmallow 将data变量序列化回 JSON,然后将其重新加载,这似乎效率很低。
我真的很喜欢有这么简单的东西
@blp.arguments(DogSchema)
@blp.response(DogSchema)
def put(self, data, dog_id):
"""Update existing dog"""
try:
dog = Dog.query.get(dog_id)
except Exception as e:
abort(404, message="Item not found - %s" % e)
dog.update(data)
db.session.commit()
return dog
Run Code Online (Sandbox Code Playgroud)
但这似乎并不存在,所以希望有人可以帮助我。
谢谢!
您可以为您的类指定update方法:Dog
class Dog(db.Model):
...
def update(self, data):
for k, v in data.items():
setattr(self, k, v)
return self
Run Code Online (Sandbox Code Playgroud)
然后根据需要使用它:
try:
dog = Dog.query.get(dog_id)
except Exception as e:
abort(404, message="Item not found - %s" % e)
dog.update(data)
db.session.commit()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1521 次 |
| 最近记录: |