【问题标题】:Python Flask download/upload database table in cvs/xlsx formatPython Flask 以 csv/xlsx 格式下载/上传数据库表
【发布时间】:2020-06-15 22:32:45
【问题描述】:

我的烧瓶应用程序上有一个下载按钮,我正在尝试添加允许用户以 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')

【问题讨论】:

    标签: python flask export-to-csv export-to-excel


    【解决方案1】:

    writerows 期待一个可迭代的,也就是说,一个列表、元组或其他 iterable object。查看您的代码,我很清楚一个问题是,您不知道自己在写什么列。例如,假设您要导出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)
    

    【讨论】:

    • 我尝试了解决方案,但它返回空 CSV。你可能知道为什么
    • 书籍是否返回行?或者,也许在你完成后调用 si.flush() ?我不确定。
    • 书籍正在返回行,但由于某种原因,您建议的代码不起作用。我也尝试过使用 flush()
    • @Stevan Stankovic... 我只看到这个答案,因为我遇到了同样的问题。如果 send_file 行被 return send_file(BytesIO(si.read().encode('utf8')), attachment_filename="export.csv", as_attachment=True, )
    【解决方案2】:

    以下解决方案适用于我:

    from io import StringIO
    import csv
    # Download shops as CSV
    @bp_dashboard.route('/shops', methods=['GET'])
    @login_required
    def shops():
        export_columns = ['type', 'name', 'comment']
        si = StringIO()
        cw = csv.writer(si, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL)
        cw.writerow(export_columns)
        for shops in shops.query.all():
            cw.writerow([str(getattr(shops, col)) for col in export_columns])
        output = make_response(si.getvalue())
        output.headers["Content-Disposition"] = "attachment; filename=shops.csv"
        output.headers["Content-type"] = "text/csv"
        return output
    

    【讨论】:

      猜你喜欢
      • 2016-01-20
      • 2020-04-03
      • 1970-01-01
      • 2018-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多