主要模型的创建/编辑视图中的次要 Table 属性
Secondary Table Attributes in Create / Edit Views for primary models
我希望能够在创建或编辑任一主要 tables。因此,当我编辑其中一个主要 table 并添加与另一个模型的关系时(隐式使用次要 table),我希望能够访问/编辑该次要关系的属性。
更具体地说:
型号
# "Primary" table
class Paper(db.Model):
__tablename__ = 'papers'
...
chapters = db.relationship(Chapter, secondary="chapter_paper")
...
# "Primary" table
class Chapter(db.Model):
...
papers = db.relationship('Paper', secondary="chapter_paper")
...
# "Secondary" table
class ChapterPaper(db.Model):
__tablename__ = 'chapter_paper'
paper_id = db.Column(db.Integer,
db.ForeignKey('papers.id'),
primary_key=True)
chapter_id = db.Column(db.Integer,
db.ForeignKey('chapters.id'),
primary_key=True)
### WANT TO EDIT
printed = db.Column(db.Boolean, default=False)
note = db.Column(db.Text, nullable=True)
### WANT TO EDIT
paper = db.relationship('Paper',
backref=db.backref("chapter_paper_assoc",
lazy='joined'),
lazy='joined')
chapter = db.relationship(Chapter,
backref=db.backref("chapter_paper_assoc",
lazy='joined'),
lazy='joined')
所以,对于这个例子,我希望能够从 flask admin 中 Paper 和 Chapter 的创建/编辑表单编辑 ChapterPaper 的“打印”和“注释”属性。
模型视图
# MainModelView subclasses flask_admin.contrib.sqla.ModelView
class PaperModelView(MainModelView):
...
form_columns = (
'title',
'abstract',
'doi',
'pubmed_id',
'link',
'journals',
'keywords',
'authors',
'chapters',
)
# Using form_columns allows CRUD for the many to many
# relation itself, but does not allow access to secondary attributes
...
所以,老实说,我不知道该怎么做。如果我将表单字段添加为附加项,然后手动验证它们......? (我不知道该怎么做)
即便如此,向表单添加额外的字段并不能真正涵盖多个模型。任何人都可以告诉我如何做到这一点,或者给我指点一个教程/甚至是来自某个随机项目一部分的代码的相关示例吗?
谢谢!
好吧,这是很多工作,需要很多 RTFM,但一旦开始,它就非常简单了。
没有整洁的方法 API 是扩展模型视图并用您自己的表单替换创建/编辑表单。
这是我的表格class:
class ExtendedPaperForm(FlaskForm):
title = StringField()
abstract = TextAreaField()
doi = StringField()
pubmed_id = StringField()
link = StringField()
journals = QuerySelectMultipleField(
query_factory=_get_model(Journal),
allow_blank=False,
)
issue = StringField()
volume = StringField()
pages = StringField()
authors = QuerySelectMultipleField(
query_factory=_get_model(Author),
allow_blank=False,
)
keywords = QuerySelectMultipleField(
query_factory=_get_model(Keyword),
allow_blank=True,
)
chapters_printed = QuerySelectMultipleField(
query_factory=_get_model(Chapter),
allow_blank=True,
label="Chapters (Printed)",
)
chapters = QuerySelectMultipleField(
query_factory=_get_model(Chapter),
allow_blank=True,
label="Chapters (All)",
)
实现此功能的重要部分是 on_model_change 方法,该方法在保存模型之前执行操作。
...
def on_model_change(self, form, model, is_created):
"""
Perform some actions before a model is created or updated.
Called from create_model and update_model in the same transaction (if it has any meaning for a store backend).
By default does nothing.
Parameters:
form – Form used to create/update model
model – Model that will be created/updated
is_created – Will be set to True if model was created and to False if edited
"""
all_chapters = list(set(form.chapters.data + form.chapters_printed.data))
for chapter in all_chapters:
if chapter in form.chapters_printed.data: # if chapter in both, printed takes priority
chapter_paper = ChapterPaper.query.filter_by(chapter_id=chapter.id, paper_id=model.id).first()
if not chapter_paper:
chapter_paper = ChapterPaper(chapter_id=chapter.id, paper_id=model.id)
chapter_paper.printed = True
db.session.add(chapter_paper)
journal = None
if form.journals.data:
journal = form.journals.data[0]
if journal: # Assumes only 1 journal if there are any journals in this field
issue = form.issue.data
volume = form.volume.data
pages = form.pages.data
journal_paper = JournalPaper.query.filter_by(journal_id=journal.id, paper_id=model.id).first()
if not journal_paper:
journal_paper = JournalPaper(journal_id=journal.id, paper_id=model.id)
journal_paper.issue = issue
journal_paper.volume = volume
journal_paper.pages = pages
db.session.add(journal_paper)
...
我希望能够在创建或编辑任一主要 tables。因此,当我编辑其中一个主要 table 并添加与另一个模型的关系时(隐式使用次要 table),我希望能够访问/编辑该次要关系的属性。
更具体地说:
型号
# "Primary" table
class Paper(db.Model):
__tablename__ = 'papers'
...
chapters = db.relationship(Chapter, secondary="chapter_paper")
...
# "Primary" table
class Chapter(db.Model):
...
papers = db.relationship('Paper', secondary="chapter_paper")
...
# "Secondary" table
class ChapterPaper(db.Model):
__tablename__ = 'chapter_paper'
paper_id = db.Column(db.Integer,
db.ForeignKey('papers.id'),
primary_key=True)
chapter_id = db.Column(db.Integer,
db.ForeignKey('chapters.id'),
primary_key=True)
### WANT TO EDIT
printed = db.Column(db.Boolean, default=False)
note = db.Column(db.Text, nullable=True)
### WANT TO EDIT
paper = db.relationship('Paper',
backref=db.backref("chapter_paper_assoc",
lazy='joined'),
lazy='joined')
chapter = db.relationship(Chapter,
backref=db.backref("chapter_paper_assoc",
lazy='joined'),
lazy='joined')
所以,对于这个例子,我希望能够从 flask admin 中 Paper 和 Chapter 的创建/编辑表单编辑 ChapterPaper 的“打印”和“注释”属性。
模型视图
# MainModelView subclasses flask_admin.contrib.sqla.ModelView
class PaperModelView(MainModelView):
...
form_columns = (
'title',
'abstract',
'doi',
'pubmed_id',
'link',
'journals',
'keywords',
'authors',
'chapters',
)
# Using form_columns allows CRUD for the many to many
# relation itself, but does not allow access to secondary attributes
...
所以,老实说,我不知道该怎么做。如果我将表单字段添加为附加项,然后手动验证它们......? (我不知道该怎么做)
即便如此,向表单添加额外的字段并不能真正涵盖多个模型。任何人都可以告诉我如何做到这一点,或者给我指点一个教程/甚至是来自某个随机项目一部分的代码的相关示例吗?
谢谢!
好吧,这是很多工作,需要很多 RTFM,但一旦开始,它就非常简单了。
没有整洁的方法 API 是扩展模型视图并用您自己的表单替换创建/编辑表单。
这是我的表格class:
class ExtendedPaperForm(FlaskForm):
title = StringField()
abstract = TextAreaField()
doi = StringField()
pubmed_id = StringField()
link = StringField()
journals = QuerySelectMultipleField(
query_factory=_get_model(Journal),
allow_blank=False,
)
issue = StringField()
volume = StringField()
pages = StringField()
authors = QuerySelectMultipleField(
query_factory=_get_model(Author),
allow_blank=False,
)
keywords = QuerySelectMultipleField(
query_factory=_get_model(Keyword),
allow_blank=True,
)
chapters_printed = QuerySelectMultipleField(
query_factory=_get_model(Chapter),
allow_blank=True,
label="Chapters (Printed)",
)
chapters = QuerySelectMultipleField(
query_factory=_get_model(Chapter),
allow_blank=True,
label="Chapters (All)",
)
实现此功能的重要部分是 on_model_change 方法,该方法在保存模型之前执行操作。
...
def on_model_change(self, form, model, is_created):
"""
Perform some actions before a model is created or updated.
Called from create_model and update_model in the same transaction (if it has any meaning for a store backend).
By default does nothing.
Parameters:
form – Form used to create/update model
model – Model that will be created/updated
is_created – Will be set to True if model was created and to False if edited
"""
all_chapters = list(set(form.chapters.data + form.chapters_printed.data))
for chapter in all_chapters:
if chapter in form.chapters_printed.data: # if chapter in both, printed takes priority
chapter_paper = ChapterPaper.query.filter_by(chapter_id=chapter.id, paper_id=model.id).first()
if not chapter_paper:
chapter_paper = ChapterPaper(chapter_id=chapter.id, paper_id=model.id)
chapter_paper.printed = True
db.session.add(chapter_paper)
journal = None
if form.journals.data:
journal = form.journals.data[0]
if journal: # Assumes only 1 journal if there are any journals in this field
issue = form.issue.data
volume = form.volume.data
pages = form.pages.data
journal_paper = JournalPaper.query.filter_by(journal_id=journal.id, paper_id=model.id).first()
if not journal_paper:
journal_paper = JournalPaper(journal_id=journal.id, paper_id=model.id)
journal_paper.issue = issue
journal_paper.volume = volume
journal_paper.pages = pages
db.session.add(journal_paper)
...