首页 > 解决方案 > Python Flask 以 cvs/xlsx 格式下载/上传数据库表

问题描述

我的烧瓶应用程序上有一个下载按钮,我正在尝试添加允许用户以 csv 或 excel 格式从本地书籍表中下载所有数据的功能。

我想做的另一件事是上传 excel 或 csv 文件并将数据导入书籍表中。

下载我有这个

@admin_role.route('/download')
@login_required
def post():
    si = StringIO()
    cw = csv.writer(si)
    for book in Book.query.all():
        cw.writerows(book)
    output = make_response(si.getvalue())
    output.headers["Content-Disposition"] = "attachment; filename=export.csv"
    output.headers["Content-type"] = "text/csv"
    return output

但我有错误TypeError: writerows() argument must be iterable

这是模型:

class Book(db.Model):
    """
    Create a Books table
    """

    __tablename__ = 'books'

    id = db.Column(db.Integer, primary_key=True)
    book_name = db.Column(db.String(60), index=True,unique=True)
    author = db.Column(db.String(200), index=True)
    quantity = db.Column(db.Integer)
    department_id = db.Column(db.Integer, db.ForeignKey('departments.id'))
    employees_id = db.Column(db.Integer, db.ForeignKey('employees.id'))
    publisher = db.Column(db.String(200))
    no_of_pgs = db.Column(db.Integer)
    pbs_year = db.Column(db.Integer)
    genre_id = db.Column(db.Integer, db.ForeignKey('genres.id'), nullable=False)
    read = db.Column(db.Enum('NO', 'YES'), default='NO')

    borrows = db.relationship('Borrow', backref='book',
                                lazy='dynamic')

标签: pythonflaskexport-to-csvexport-to-excel

解决方案


writerows期待一个可迭代的,也就是说,一个列表、元组或其他可迭代对象。查看您的代码,我很清楚一个问题是,您不知道自己在写什么列。例如,假设您要导出idbook_nameauthor

cw = csv.writer(si)
cw.writerow(['id', 'book_name', 'author'])    # Write header row
for book in Book.query.all():
    cw.writerows([str(book.id), book.book_name, book.author])

也许更优雅的是,您可以避免重复自己:

export_columns = ['id', 'book_name', 'author']

cw = csv.writer(si)
cw.writerow(export_columns)
for book in Book.query.all():
    cw.writerows([str(getattr(book, col)) for col in export_columns])

请注意,我明确地将所有列转换为字符串。如果您的数据库中有 Unicode,您将需要弄清楚您希望如何对这些字符串进行编码,但这是另一个主题。

就实际将文件发送给用户而言,您需要使用 Flask send_file函数。

from flask import send_file

si.seek(0)
return send_file(si, attachment_filename='export.csv', as_attachment=True)

推荐阅读