1

考虑以下我正在尝试实现的用例。我正在使用 Flask、Flask-SQLAlchemy 将用户数据存储在 SQLite 数据库中,并使用 Flask-Admin 来实现其文件管理功能。

流程是这样的:当用户登录时,他会被带到管理模块的索引视图。但是当他登录时,他的用户名被添加到初始化 FileAdmin 类时使用的路径中——这个想法是拥有用户目录,这些目录是在用户注册时由一个简单的 shell 命令创建的。因此,如果 Flask 中定义的根路径是“/files/”,而我的用户名是“rudimk”,那么在初始化文件 admin 时应该使用的路径应该是“/files/rudimk”。

问题是,当应用程序启动时,没有会话,没有用户登录 - 但文件 admin 已初始化,默认路径,在我们的例子中是“/files/”。当用户登录时,无法重新初始化文件管理类,因为它在请求上下文之外。我从 flask-admin 文档中查看了 get_base_path() ,但我无法弄清楚它在这里有什么用处。

非常感激。谢谢!

编辑 - 添加了一些我正在使用的代码。请注意,在这里,我已经删除了身份验证,并通过将用户名添加到会话来模拟经过身份验证的会话。

import os
import os.path as op

from flask import Flask, session

from flask.ext import admin
from flask.ext.admin.contrib import fileadmin


# Create flask app
app = Flask(__name__, template_folder='templates', static_folder='files')

# Create dummy secrey key so we can use flash
app.config['SECRET_KEY'] = '123456790'


# Flask views
@app.route('/')
def index():
    # Simulating a logged-in user by storing his/her username in the session.
    session["username"]
    return '<a href="/admin/">Click me to get to Admin!</a>'


if __name__ == '__main__':
    # Create directory
    username = session["username"]
    path = op.join(op.dirname(__file__), 'files/%s' %username)
    try:
        os.mkdir(path)
    except OSError:
        pass

    # Create admin interface
    admin = admin.Admin(app)
    admin.add_view(fileadmin.FileAdmin(path, '/files/%s' %username, name='Files'))

    # Start app
    app.run(debug=True)
4

1 回答 1

4

get_base_path方法在您需要做的事情中非常明确..

覆盖以自定义行为(每个用户目录等)

所以,这就是你需要做的。您需要创建一个继承自 FileAdmin 的类,覆盖该get_base_path()方法,并使用该类而不是基本 FileAdmin。如果您不熟悉什么是“覆盖”方法,您应该查找 Python 面向对象的教程。

您创建的这个新类需要覆盖get_base_path()每个用户的方法。所以,像...

class MyFileAdmin(FileAdmin):
    def get_base_path(self):
        path = FileAdmin.get_base_path(self)

        if not current_user.is_anonymous():
            return os.path.join(path, current_user.custom_path)
        else:
            return path

现在使用MyFileAdmin代替FileAdmin. 我还没有测试过这段代码,但希望这能让你走上正轨。

请注意,您在实际 FileAdmin 实例上更改路径的原始计划将不起作用。您创建一个 FileAdmin 实例,所有用户的请求都将使用相同的视图进行路由。如果您尝试这样做,您可能会遇到多线程问题。

于 2013-10-15T20:42:31.693 回答