python - Flask-Admin 中的简单多对多问题
问题描述
我正在将 Flask-Admin 添加到现有的 Flask 应用程序(使用 Python 3 和带有 SQLAlchemy 的 MySQL),我根本无法弄清楚如何获得正确呈现的多对多关系。我在这里阅读了许多关于此的问题,看起来我正在遵循正确的做法。
我有一个Quotation
表,一个Subject
表,一个QuotationSubject
表,它必须是一个实际的类而不是一个关联表,但我不关心关联表中为此目的的额外列;它们是last_modified
我不需要显示或编辑的东西。这些关系似乎在应用程序的其余部分中起作用。
修剪掉这里无关紧要的字段和定义,我有:
class Quotation(db.Model):
__tablename__ = 'quotation'
id = db.Column(db.Integer, primary_key=True)
word = db.Column(db.String(50))
description = db.Column(db.Text)
created = db.Column(db.TIMESTAMP, default=db.func.now())
last_modified = db.Column(db.DateTime, server_default=db.func.now())
subject = db.relationship("QuotationSubject", back_populates="quotation")
def __str__(self):
return self.word
class Subject(db.Model):
__tablename__ = 'subject'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
created = db.Column(db.TIMESTAMP, default=db.func.now())
last_modified = db.Column(db.DateTime, server_default=db.func.now())
quotation = db.relationship("QuotationSubject", back_populates="subject")
def __str__(self):
return self.name
class QuotationSubject(db.Model):
__tablename__ = 'quotation_subject'
id = db.Column(db.Integer, primary_key=True)
quotation_id = db.Column(db.Integer, db.ForeignKey('quotation.id'), default=0, nullable=False)
subject_id = db.Column(db.Integer, db.ForeignKey('subject.id'), default=0, nullable=False)
created = db.Column(db.TIMESTAMP, default=db.func.now())
last_modified = db.Column(db.DateTime, server_default=db.func.now())
quotation = db.relationship('Quotation', back_populates='subject', lazy='joined')
subject = db.relationship('Subject', back_populates='quotation', lazy='joined')
在我的admin.py
中,我只有:
class QuotationModelView(ModelView):
column_searchable_list = ['word', 'description']
form_excluded_columns = ['created', 'last_modified']
column_list = ('word', 'subject')
admin.add_view(QuotationModelView(Quotation, db.session))
就是这样。
在我list
看来,我没有看到subject
值,而是在表中获得了相关的条目QuotationSubject
,例如
test <QuotationSubject 1>, <QuotationSubject 17>, <QuotationSubject 18>
book <QuotationSubject 2>
同样,在我create
看来,我不是从 QuotationSubject 表中获得一个包含十几个主题的列表,而是获得一个包含所有内容的巨大列表。
我看过一些inline_models
东西,这里的一些帖子建议,这也没有奏效,但无论如何还有其他帖子(例如,具有多对多关系模型的 Flask-Admin 视图)表明我我做的应该工作。如果有人能指出我做错了什么,我将不胜感激。
解决方案
首先,我担心您的问题中缺少某些内容,因为我没有看到Citation
定义的类。但这似乎不是问题。
Flask 中多对多关系最经典的例子是用户角色。以下是用户 M2M 关系的工作角色的样子:
class RolesUsers(Base):
__tablename__ = 'roles_users'
id = db.Column(db.Integer(), primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey('user.id'))
role_id = db.Column(db.Integer(), db.ForeignKey('role.id'))
class Role(RoleMixin, Base):
__tablename__ = 'role'
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
def __repr__(self):
return self.name
class User(UserMixin, Base):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), index=True, unique=True)
roles = db.relationship('Role', secondary='roles_users',
backref=db.backref('users', lazy='dynamic'))
在 Flask-Admin 中:
from user.models import User, Role
admin.add_view(PVCUserView(User, db.session))
admin.add_view(PVCModelView(Role, db.session))
请注意,关系只声明一次,backref
所以它是双向的。看起来您正在back_populates
为此使用,我认为这是等效的。
对于您所描述的情况,您的代码似乎直接声明了与 M2M 表的关系。这真的是你想要的吗?您说您不需要访问 Flask-Admin 的 QuotationSubject 表中的额外列。但是你在其他地方需要它们吗?调用quotation
或subject
实际返回QuotationSubject
. 我相信这就是 Flask-Admin 在创建视图中列出所有 QuotationSubject 行的原因。
所以我的建议是尝试将您的关系设置为直接指向目标模型类,同时将 M2M 表作为secondary
.
如果您想在其他地方访问关联模型(并且如果由于某种原因它真的不能成为关联代理),那么在每个明确指向它的模型类中创建第二个关系。然后,您可能需要在 Flask-Admin 中使用form_excluded_columns
和排除该关系column_exclude_list
。
推荐阅读
- c# - OmniSharp MSBuild ProjectManager 无法更新我的 .csproj 文件
- embedded - 最好的 SPI 波特率预分频器
- angular - 无法激活已激活的出口离子
- node.js - 对特定条件有限制的环回查询/查找
- php - 如何制作 php tree optgroup?
- python - 如何使用树莓派检测python中的按键
- javascript - 在冒号上拆分所有表单输入并换行
- php - 如何将真实条件的值分配给laravel中if else条件之外的变量?
- r - 将 NA 转换为特定列的虚拟对象
- python - 为什么我的 Python 包被导入为“命名空间”模块,如何正确导入模块?