时间:2021-07-01 10:21:17 帮助过:4人阅读
多对多关系
一对多关系、多对一关系和一对一关系至少都有一侧是单个实体,所以记录之间的联系通过外键实现,让外键指向这个实体。但是,你要如何实现两侧都是“多”的关系呢?
下面以一个典型的多对多关系为例,即一个记录学生和他们所选课程的数据库。很显然,你不能在学生表中加入一个指向课程的外键,因为一个学生可以选择多个课程,一个外键不够用。同样,你也不能在课程表中加入一个指向学生的外键,因为一个课程有多个学生选择。两侧都需要一组外键。这种问题的解决方法是添加第三张表, 这个表称为关联表。现在,多对多关系可以分解成原表和关联表之间的两个一对多关系。
下图 描绘了学生和课程之间的多对多关系。
上图中的多对多关系使用的代码表示如下:
registrations = db.Table('registrations', db.Column('student_id', db.Integer, db.ForeignKey('students.id')), db.Column('class_id', db.Integer, db.ForeignKey('classes.id')) ) class Student(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String) classes = db.relationship('Class',secondary=registrations, backref=db.backref('students', lazy='dynamic'), lazy='dynamic') class Class(db.Model): id = db.Column(db.Integer, primary_key = True) name = db.Column(db.String)
下面来看一个实际的例子:因为在设计中学生会转学院,所以,学生与学院是多对多的关系
1.定义模型
class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(100), unique=True, index=True) .............省略其他字段 departments=db.relationship('Department', secondary=user_department, backref=db.backref('users',lazy='dynamic'), lazy='dynamic')
class Department(db.Model): __tablename__ = 'departments' id = db.Column(db.Integer, primary_key=True) department = db.Column(db.String(100))
user_department = db.Table('user_department', db.Column('user_id', db.Integer, db.ForeignKey('users.id'), primary_key=True), db.Column('department_id', db.Integer, db.ForeignKey('departments.id'), primary_key=True) )2.定义表单:
class SmForm(Form): name = StringField('真实姓名', validators=[Length(0, 64)]) ....................省略其他字段 is_departmentChange = BooleanField('是否转过学院') pre_department = SelectField('原学院:', coerce=int) cut_department = SelectField('现学院:', coerce=int) submit = SubmitField('Submit') #下拉菜单初始化 def __init__(self, user, *args, **kwargs): super(SmForm, self).__init__(*args, **kwargs) <strong>self.pre_department.choices = [(pre_department.id, pre_department.department) for pre_department in Department.query.order_by(Department.department).all()] self.cut_department.choices = [(cut_department.id, cut_department.department) for cut_department in Department.query.order_by(Department.department).all()]</strong> self.user = user3.定义路由:
@main.route('/sm', methods=['GET', 'POST']) @login_required @main.errorhandler(404) def sm(): user = User.query.filter_by(email=current_user.email).first() form = SmForm(user) if user.is_realname ==False: if form.validate_on_submit(): # User的学院更新 删除旧的数据,<strong>联合删除 usr = current_user._get_current_object() deparment = user.departments.all() for de in deparment: de.users.remove(usr)</strong> ........................省略其他 user.is_departmentChange = form.is_departmentChange.data <strong>#向关系表中添加 user.departments.append(Department.query.get(form.pre_department.data)) user.departments.append(Department.query.get(form.cut_department.data)) db.session.add(user) db.session.commit()</strong> return redirect(url_for('.sm_success')) return render_template('sm.html', form=form)4.渲染模板(省略)
Flask 数据库多对多关系
标签: