SQLAlchemy и Flask-Admin: теги для записей со связь Many to Many
Для нашего блога решил добавить теги, чтобы похожие записи было проще искать и вообще это модно сейчас. Ранее использовал обычный массив с ForeignKey, и это работает, но... Всегда есть но, в Flask-Admin для того чтобы появился мультиселект с вариантами из другой таблички этого уже недостаточно.
И так начнем с проблемы:
Есть много тегов и также немало статей, их нужно связать методом "многий ко многим", а для удобства редактирование в админ панели, в форме редактирования статьи, должен появится мультиселект с этими самыми тегами.
Начнем с модельки самого тега, тут есть одна особенность:
class TagModel(db.Model):
__tablename__ = 'tag'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
weight = db.Column(db.Integer, index=True, default=0)
create_date = db.Column(db.DateTime, default=datetime.datetime.now)
def __str__(self):
return self.name
Для того что-бы Flask-Admin в селекте выводил нормально название добавляем функцию __str__, она то как раз и будет отвечать за формирование имени в селекте.
Далее модель статьи:
class ArticleModel(db.Model):
__tablename__ = 'article'
_cover = None
id = db.Column(db.Integer, primary_key=True)
chpu = db.Column(db.String)
title = db.Column(db.String)
keywords = db.Column(db.String)
description = db.Column(db.String)
state = db.Column(db.Integer, index=True, default=ARTICLE_EDIT)
tags = db.relationship(TagModel, secondary=article_tags_meta)
cover_id = db.Column(db.Integer)
name = db.Column(db.String)
preview = db.Column(db.String)
body = db.Column(db.TEXT)
update_date = db.Column(db.DateTime, default=datetime.datetime.now)
create_date = db.Column(db.DateTime, default=datetime.datetime.now)
Здесь мы добавиляем отношение:
tags = db.relationship(TagModel, secondary=article_tags_meta)
article_tags_meta это промежуточная таблица со связями, выглядет она следующим образом:
article_tags_meta = db.Table(
'article_tags',
db.Model.metadata,
db.Column('article_id', db.Integer, db.ForeignKey('article.id')),
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
extend_existing=True
)
И по результату, без лишней магии и телодвижений получаем в админ панели:
