Flask sqlalchemy chèn nhiều dữ liệu


78

Tôi đang cố gắng tạo mối quan hệ nhiều đến nhiều ở đây trong Flask-SQLAlchemy , nhưng có vẻ như tôi không biết cách điền vào "cơ sở dữ liệu số nhận dạng nhiều đến nhiều" . Bạn có thể vui lòng giúp tôi hiểu những gì tôi đang làm sai và nó trông như thế nào?

class User(db.Model):
    __tablename__ = 'users'
    user_id = db.Column(db.Integer, primary_key=True)
    user_fistName = db.Column(db.String(64))
    user_lastName = db.Column(db.String(64))
    user_email = db.Column(db.String(128), unique=True)


class Class(db.Model):
    __tablename__ = 'classes'
    class_id = db.Column(db.Integer, primary_key=True)
    class_name = db.Column(db.String(128), unique=True)

và sau đó là cơ sở dữ liệu định danh của tôi:

student_identifier = db.Table('student_identifier',
    db.Column('class_id', db.Integer, db.ForeignKey('classes.class_id')),
    db.Column('user_id', db.Integer, db.ForeignKey('users.user_id'))
)

cho đến nay nó trông như thế này khi tôi cố gắng chèn dữ liệu vào cơ sở dữ liệu.

# User
user1 = User(
            user_fistName='John',
            user_lastName='Doe',
            user_email='john@doe.es')

user2 = User(
            user_fistName='Jack',
            user_lastName='Doe',
            user_email='jack@doe.es')

user3 = User(
            user_fistName='Jane',
            user_lastName='Doe',
            user_email='jane@doe.es')

db.session.add_all([user1, user2, user3])
db.session.commit()

# Class
cl1 = Class(class_name='0A')
cl2 = Class(class_name='0B')
cl3 = Class(class_name='0C')
cl4 = Class(class_name='Math')
cl5 = Class(class_name='Spanish')
db.session.add_all([cl1, cl2, cl3, cl4, cl5])
db.session.commit()

Bây giờ vấn đề của tôi là, làm cách nào để thêm vào nhiều cơ sở dữ liệu, vì tôi thực sự không thể tạo đối tượng 'student_identifier'? Nếu tôi có thể, nó có thể trông như thế này:

# Student Identifier
sti1  = StiClass(class_id=cl1.class_id, class_name=user1.user_id)
sti2  = StiClass(class_id=cl3.class_id, class_name=user1.user_id)
sti3  = StiClass(class_id=cl4.class_id, class_name=user1.user_id)
sti4  = StiClass(class_id=cl2.class_id, class_name=user2.user_id)
db.session.add_all([sti1, sti2, sti3, sti4])
db.session.commit()

Làm cách nào để chèn ORM vào một bảng nhiều đến nhiều?

Câu trả lời:


146

Bạn không cần thêm bất cứ thứ gì trực tiếp vào bảng liên kết của mình, SQLAlchemy sẽ thực hiện điều đó. Điều này ít nhiều là từ tài liệu SQLAlchemy :

association_table = db.Table('association', db.Model.metadata,
    db.Column('left_id', db.Integer, db.ForeignKey('left.id')),
    db.Column('right_id', db.Integer, db.ForeignKey('right.id'))
)

class Parent(db.Model):
    __tablename__ = 'left'
    id = db.Column(db.Integer, primary_key=True)
    children = db.relationship("Child",
                    secondary=association_table)

class Child(db.Model):
    __tablename__ = 'right'
    id = db.Column(db.Integer, primary_key=True)


p = Parent()
c = Child()
p.children.append(c)
db.session.add(p)
db.session.commit()

Do đó, mẫu của bạn sẽ như thế này:

student_identifier = db.Table('student_identifier',
    db.Column('class_id', db.Integer, db.ForeignKey('classes.class_id')),
    db.Column('user_id', db.Integer, db.ForeignKey('students.user_id'))
)

class Student(db.Model):
    __tablename__ = 'students'
    user_id = db.Column(db.Integer, primary_key=True)
    user_fistName = db.Column(db.String(64))
    user_lastName = db.Column(db.String(64))
    user_email = db.Column(db.String(128), unique=True)


class Class(db.Model):
    __tablename__ = 'classes'
    class_id = db.Column(db.Integer, primary_key=True)
    class_name = db.Column(db.String(128), unique=True)
    students = db.relationship("Student",
                               secondary=student_identifier)

s = Student()
c = Class()
c.students.append(s)
db.session.add(c)
db.session.commit()

14
Giả sử học sinh của tôi đã tồn tại trong một bảng. Làm cách nào để nối chúng vào một lớp học mà không phải truy vấn toàn bộ dữ liệu cho từng học sinh mỗi lần (chỉ sử dụng phím phía trước)?
axwell

@axwell, Nếu bạn thường xuyên yêu cầu học sinh cho lớp (tức là khi kiểm tra về bản cập nhật), bạn có thể mối quan hệ hòa hợp với 'subquery' lười biếng = như thế này: students = db.relationship("Student", secondary=student_identifier, lazy='subquery', backref=db.backref('classes', lazy=True))
Andrii Danyleiko

@axwell Bạn cũng có thể làm chèn như thế này nếu học sinh đã tồn tại: session.execute( student_identifier.insert(), params={"class_id": class_id, "user_id": user_id}, )
Edword

20

Trước hết, student_identifierđược định nghĩa là một bảng phản chiếu SQLAlchemy không phải là một cơ sở dữ liệu.

Thông thường, nếu bạn có tất cả các thiết lập mối quan hệ đúng cách giữa các mô hình và đối tượng bảng phản chiếu, bạn sẽ chỉ cần xử lý các mô hình liên quan (bằng cách thêm các đối tượng mô hình vào mối quan hệ InstrumentList) để chèn dữ liệu vào bảng phản chiếu, ví dụ: answer @ mehdi-sadeghi đã cung cấp ở trên.

Tuy nhiên, thực sự có một cách để chèn trực tiếp vào các bảng phản chiếu nếu bạn không muốn thiết lập mối quan hệ. Ví dụ:

statement = student_identifier.insert().values(class_id=cl1.id, user_id=sti1.id)
db.session.execute(statement)
db.session.commit()

Sau đó, bạn sẽ có thể thấy rằng một hàng quan hệ nhiều-nhiều được chèn vào student_identifierbảng phản chiếu. Đừng quên cam kết sau khi bạn thực hiện mỗi câu lệnh SQL vì nó được thực hiện trong một giao dịch.

Hy vọng rằng sẽ giúp bạn với một cách tiếp cận thay thế.


làm cách nào để nhập bảng phản chiếu hoặc bảng liên kết này?
jibin Mathew

@jibinmathew giống như cách bạn làm với các lớp và các ký hiệu khác.
Devy

@jibinmathew Tôi cũng gặp sự cố khi nhập bảng kết hợp, vì vậy tôi nhập bảng cục bộ, chính xác ở trên nơi tôi gọi đó.
Tri

1
@GofyandKitty có thể là một chỉ báo về sự phụ thuộc / nhập vòng tròn trong cơ sở mã của bạn để bạn cần sử dụng nhập cục bộ (để cung cấp không gian tên) để làm cho nó hoạt động.
Devy

1
Cảm ơn rất nhiều vì đã chia sẻ giải pháp này. Bạn đã cứu tôi theo đúng nghĩa đen
Chidiebere

-1

Để mở rộng câu trả lời cowgills, bạn cũng có thể thêm nhiều mục nhập cùng một lúc bằng cách sử dụng extend:

class_ = db.session.query(Class).first()
new_students = db.session.query(Student).all()
class_.students.extend(new_students)
db.session.add(class_)
db.session.commit()
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.