如何在Flask / SQLAlchemy中显示包含多对多查询结果的列

时间:2014-07-09 04:32:57

标签: python flask flask-sqlalchemy flask-admin

我正在尝试通过构建一个简单的Wiki(大量基于a Flask-Admin example)来学习Python / Flask / SQLAlchemy但是我很难理解如何从我的多对多关系中获取一个新列来显示

我已经成功创建了Wiki,并为标签创建了一个多对多的关系表,没有问题(并且标签在我看到的情况下正常工作),但我想将标签显示为列,并且可以没有得到逻辑。

目标:我想显示一个列,显示多对多关联表引用的标记。

以下是我想要完成的图片:

A table with a column named Tag(s) with two rows.  Row #1 contains the text "Tag 1, Tag 4". Row #2 contains the text "Tag 4, Tag 5".

以下是我认为的相关代码:

wiki_tags_table = db.Table('wiki_tags', db.Model.metadata,
                           db.Column('wiki_id', db.Integer, db.ForeignKey('wiki.id')),
                           db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'))
                           )

class Wiki(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), unique=True)
    description = db.Column(db.Text)
    path = db.Column(db.Unicode(256))
    date_added = db.Column(db.DateTime)
    tags_id = db.Column(db.Integer, db.ForeignKey('tag.id'))
    tags = db.relationship('Tag', secondary=wiki_tags_table, backref=db.backref('wiki_tags_table', lazy='dynamic'))

    def __unicode__(self):
        return self.item

class WikiAdmin(sqla.ModelView):

    column_exclude_list = ['path']

    column_hide_backrefs = False

    form_overrides = {
        'path': form.FileUploadField
    }

    form_args = {
        'path': {
            'label': 'File',
            'base_path': file_path
        }
    }

    column_searchable_list = ('title', 'description', 'path')

    def __init__(self, session):
        super(WikiAdmin, self).__init__(Wiki, session)

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(64))

    def __unicode__(self):
        return self.name

我一直在引用这些文档(主要是尝试使用backref的变体),但尚未弄明白:

3 个答案:

答案 0 :(得分:1)

我不确定这是否会有所帮助,因为我在学习自己。但我有一个类似的问题,我想在一个外键表中显示一个列'并且这样做了:

我的modle.py

  from app import db

class Member(db.Model):
    __tablename__ = 'members'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(64), index=True)
    phone = db.Column(db.String(10), index=True)
    email = db.Column(db.String(120), index=True, unique=True)
    grade = db.relationship('Grade', backref='member')
    attendance = db.relationship('Attendance', backref='member')

    def __repr__(self):
        return '<User %r>' % self.name


class Grade(db.Model):
    __tablename__ = 'grades'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    member_id = db.Column(db.Integer, db.ForeignKey('members.id'))
    grade = db.Column(db.String(10))
    grade_date = db.Column(db.Date)

    def __repr__(self):
        return '<Grading %r>' % self.id

    def __str__(self):
        return self.grade

    def __unicode__(self):
        return self.grade


class Attendance(db.Model):
    __tablename__ = 'attendance'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    id_member = db.Column(db.Integer, db.ForeignKey('members.id'))
    attend_date = db.Column(db.Date)

    def __repr__(self):
        return '<Attenance %r>' % self.id

my views.py

from app.models import Member, Grade, Attendance
from app import app, admin, db
from flask_admin import BaseView, expose
from flask_admin.contrib.fileadmin import FileAdmin
from flask_admin.contrib.sqla import ModelView
import os.path as op


class AdminView(ModelView):
    column_display_pk = True  # optional, but I like to see the IDs in the list
    column_hide_backrefs = False
    # column_list = ('id', 'name', 'parent')
    create_modal = True
    edit_modal = True


class MemberAdmin(ModelView):
    column_display_pk = True  # optional, but I like to see the IDs in the list
    column_hide_backrefs = False
    can_view_details = True
    create_modal = True
    edit_modal = True
    form_columns = ['name', 'phone', 'email', 'grade', 'attendance']
    column_details_list = ['name', 'phone', 'email', 'grade', 'attendance']
    column_searchable_list = ['name', 'email']
    column_list = ('id', 'name', 'phone','email','grade')


class GradeAdmin(ModelView):
    column_display_pk = True  # optional, but I like to see the IDs in the list
    column_hide_backrefs = False
    column_list = ('id', 'member', 'grade', 'grade_date')
    form_choices = {'grade': [('Beginner', 'Beginner'), ('Yellow', 'Yellow'), ('Orange', 'Orange'),
                              ('Green 1', 'Green 1'), ('Green 2', 'Green 2'), ('Blue 1', 'Blue 1'),
                              ('Blue 2', 'Blue 2'), ('Purple 1', 'Purple 1'), ('Purple 2', 'Purple 2'),
                              ('Brown 1', 'Brown 1'), ('Brown 2', 'Brown 2'), ('Red 1', 'Red 1')]}


admin.add_view(MemberAdmin(Member, db.session, endpoint='member', category='Admin'))
admin.add_view(GradeAdmin(Grade, db.session, endpoint='grades', category='Admin'))
admin.add_view(ModelView(Attendance, db.session, endpoint='attendance', category='Admin'))

由于我不知道自己在做什么(还),我认为让我看到我的会员模型的列,加上来自Grade模型的额外列是这些行在类MemberAdmin(ModelView)中:

column_hide_backrefs = False
can_view_details = True
...
form_columns = ['name', 'phone', 'email', 'grade', 'attendance']

答案 1 :(得分:0)

relationship属性将相关表加载为对象列表,因此您应该能够在视图中打印所有wiki项和所有相关标签:

for wiki_item in Wiki.query.all():
    print wiki_item.title
    for tag in wiki_item.tags:
        print tag.name 

如果你尝试会怎么样?

答案 2 :(得分:0)

我现在需要实现相同的功能,对我有用的只是在ViewModel类中添加column_list字段,所以在这种情况下,那将是

class WikiAdmin(sqla.ModelView):

    ...
    column_list = ('title', 'description', 'dataadded', 'tags')

这是一个老问题,但这是第一个线索(并且,可以说是唯一相关的)我在试图弄清楚如何做到这一点时偶然发现,所以也许这个答案会节省一些人的时间