Flask-SQLalchemy cập nhật thông tin của hàng


Câu trả lời:


205

Lấy một đối tượng bằng cách sử dụng hướng dẫn được hiển thị trong tài liệu Flask-SQLAlchemy . Sau khi bạn có đối tượng mà bạn muốn thay đổi, hãy thay đổi đối tượng đó. Sau đó db.session.commit(),.

Ví dụ:

admin = User.query.filter_by(username='admin').first()
admin.email = 'my_new_email@example.com'
db.session.commit()

user = User.query.get(5)
user.name = 'New Name'
db.session.commit()

Flask-SQLAlchemy dựa trên SQLAlchemy, vì vậy hãy nhớ kiểm tra Tài liệu SQLAlchemy .


2
Cảm ơn Mark. Một thứ khác. Tôi đã thấy nó được thực hiện như thế này 'db.add (user)' rồi 'dv.session.commit ()'. Tại sao cả hai đều hoạt động? và sự khác biệt là gì?
pocorschi

11
Điều này liên quan đến sự khác biệt giữa các đối tượng tạm thời, tách rời và đính kèm trong SQLAlchemy (xem sqlalchemy.org/docs/orm/session.html#what-does-the-session-do ). Ngoài ra, hãy đọc bình luận của Michael Bayer về danh sách gửi thư ( groups.google.com/group/sqlalchemy/browse_thread/thread/… ) để biết thêm thông tin.
Mark Hildreth

1
Nếu bạn vẫn còn bối rối về sự khác biệt sau khi đọc qua đó, hãy cân nhắc đặt một câu hỏi khác.
Mark Hildreth

nếu kiểu dữ liệu cột là json, hãy sử dụng phương pháp dưới đây. bashelton.com/2014/03/…
Aram

@MarkHildreth Tôi không thể cập nhật giá trị ngày giờ vào trường, tôi nên làm gì? cột là uesd_at = db.Column(db.DateTime)Tôi chỉ chạy obj.used_at = datetime.datetime.now() db.session.commit()Nhưng không đặt giá trị cho trường.
Rukeith

96

Có một phương thức updatetrên đối tượng BaseQuery trong SQLAlchemy, được trả về bởi filter_by.

admin = User.query.filter_by(username='admin').update(dict(email='my_new_email@example.com')))
db.session.commit()

Lợi thế của việc sử dụng updatehơn thay đổi thực thể đến khi có nhiều đối tượng được cập nhật.

Nếu bạn muốn cấp add_userquyền cho tất cả các admins,

rows_changed = User.query.filter_by(role='admin').update(dict(permission='add_user'))
db.session.commit()

Lưu ý rằng filter_bylấy các đối số từ khóa (chỉ sử dụng một =) trái ngược với filterlấy một biểu thức.


1
trong truy vấn đầu tiên, kết quả được đặt tên là admin, có thể gây hiểu lầm vì kết quả sẽ là số hàng được cập nhật. Phải không?
Vikas Prasad

và có cách nào, nơi tôi có thể lấy các Usermục bị ảnh hưởng bởi truy vấn, không phải số lượng người dùng bị ảnh hưởng?
Vikas Prasad

số hàng phù hợp
Vikas Prasad

18

Điều này không hoạt động nếu bạn sửa đổi thuộc tính đã chọn của mô hình. Các thuộc tính đã chọn phải được thay thế để kích hoạt cập nhật:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from pprint import pprint

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqllite:////tmp/users.db'
db = SQLAlchemy(app)


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)
    data = db.Column(db.PickleType())

    def __init__(self, name, data):
        self.name = name
        self.data = data

    def __repr__(self):
        return '<User %r>' % self.username

db.create_all()

# Create a user.
bob = User('Bob', {})
db.session.add(bob)
db.session.commit()

# Retrieve the row by its name.
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {}

# Modifying data is ignored.
bob.data['foo'] = 123
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {}

# Replacing data is respected.
bob.data = {'bar': 321}
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {'bar': 321}

# Modifying data is ignored.
bob.data['moo'] = 789
db.session.commit()
bob = User.query.filter_by(name='Bob').first()
pprint(bob.data)  # {'bar': 321}

1
Cách tiếp cận tốt nhất trong những trường hợp như vậy là gì?
kampta

Bạn sẽ phải sao chép datavà gán lại nó.
sas

@sas Ý bạn là gì?
Mote Zart

Bạn sẽ cần sao chép và gán cho thuộc tính dữ liệu để kích hoạt cơ chế cập nhật. Hãy xem câu trả lời bên dưới:user.data = data
sas

9

Chỉ cần gán giá trị và cam kết chúng sẽ hoạt động cho tất cả các loại dữ liệu trừ các thuộc tính JSON và Pickled. Vì kiểu ngâm đã được giải thích ở trên, tôi sẽ lưu ý một cách hơi khác nhưng dễ dàng để cập nhật JSON.

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)
    data = db.Column(db.JSON)

def __init__(self, name, data):
    self.name = name
    self.data = data

Giả sử mô hình như trên.

user = User("Jon Dove", {"country":"Sri Lanka"})
db.session.add(user)
db.session.flush()
db.session.commit()

Thao tác này sẽ thêm người dùng vào cơ sở dữ liệu MySQL với dữ liệu {"country": "Sri Lanka"}

Việc sửa đổi dữ liệu sẽ bị bỏ qua. Mã của tôi không hoạt động như sau.

user = User.query().filter(User.name=='Jon Dove')
data = user.data
data["province"] = "south"
user.data = data
db.session.merge(user)
db.session.flush()
db.session.commit()

Thay vì phải thực hiện công việc khó khăn là sao chép JSON sang một mệnh lệnh mới (không gán nó cho một biến mới như ở trên), mà lẽ ra phải làm việc, tôi đã tìm ra một cách đơn giản để làm điều đó. Có một cách để gắn cờ hệ thống mà JSON đã thay đổi.

Sau đây là mã làm việc.

from sqlalchemy.orm.attributes import flag_modified
user = User.query().filter(User.name=='Jon Dove')
data = user.data
data["province"] = "south"
user.data = data
flag_modified(user, "data")
db.session.merge(user)
db.session.flush()
db.session.commit()

Điều này hoạt động như một sự quyến rũ. Có một phương pháp khác được đề xuất cùng với phương pháp này ở đây Hy vọng tôi đã giúp được một số.


2
db.session.merge(user)thêm mã này đã làm việc cho tôi, FYI.
Jeff Bluemel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.