如何在 Python Flask 中散列路由?

问题描述 投票:0回答:2

我的目标很简单,我创建了一个接收 ID 的路由。

@app.route('/afbase/<int:pid>', methods=["GET", "PATCH", "DELETE"])
# We defined the page that will retrieve some info
def show(pid):
    new_person = People.query.filter_by(pid=pid).first()

我不希望这个 ID 显示给最终用户。如何散列路由或部分散列路由?

current url screenshot

这个路由会接收到一个名为PID的变量,你可以看到,这个PID变量可以看作是一个ID。不区分大小写,但不能在浏览器 URL 上显示。

我尝试使用 hashlib 但没有成功。

python flask hash routes flask-sqlalchemy
2个回答
2
投票

您可以使用

hashids
库对整数 ID 进行编码和解码。首先,
pip install hashids
。然后,创建一些实用函数。

# utils.py
from flask import current_app
from hashids import Hashids

def create_hashid(id):
    hashids = Hashids(min_length=5, salt=current_app.config['SECRET_KEY'])
    hashid = hashids.encode(id)
    return hashid

def decode_hashid(hashid):
    hashids = Hashids(min_length=5, salt=current_app.config['SECRET_KEY'])
    id = hashids.decode(hashid)
    return id

接下来,创建一个全局环境变量,这样您就可以从您的 jinja2 模板中调用 create_hashid 函数:

# app.py
from utils import create_hashid
app.jinja_env.globals.update(create_hashid=create_hashid)

以下是如何从模板中的链接调用该函数:

# index.html
<a href="{{ url_for('invoice.view_invoice', hashid=create_hashid(invoice.id) ) }}">View Invoice</a>

最后,你的视图函数:

# views.py
@blueprint.route('/dashboard/invoice/<hashid>')
@login_required
def view_invoice(hashid):
    invoice_id = decode_hashid(hashid)
    invoice = Invoice.query.filter_by(
        user_id=current_user.id,
        id=invoice_id
    ).first_or_404()

return render_template(
    'dashboard/invoice/view_invoice.html',
    invoice=invoice
)

0
投票

我知道 OP 已经有了答案。然而,我发现了一个很棒的 Flask 扩展,叫做 Flask-Hashids,它基本上基于 Bob 的答案中使用的 hashids,但更优雅。

可重现的代码

from flask import Flask, url_for
from flask_hashids import HashidMixin, Hashids
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SECRET_KEY'] = 'super-secret-key'
app.config['HASHIDS_SALT'] = 'must-be-different-from-SECRET_KEY'
app.config['HASHIDS_MIN_LENGTH'] = 16
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db_dev.sqlite3'

db = SQLAlchemy(app)
hashids = Hashids(app)

class User(HashidMixin, db.Model): # Add the hashid mixin class
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False)

    @property
    def url(self):
        # The HashidConverter encodes the given id to a hashid in the URL
        return url_for('user', user_id=self.id)

    def to_json(self):
        return {"id": self.hashid, "name": self.name}

@app.before_first_request
def create_user_table():
    db.create_all()
    # Add some dummy data
    db.session.add_all([User(name='John Doe'), User(name='Jane Doe')])
    db.session.commit()

@app.route('/user')
def users():
    users = User.query.all() # get all users
    return [user.to_json() for user in users], 200

输出

[
    {
        "id": "RxvDmWYG8neBo098", # Hashed ID
        "name": "John Doe"
    },
    {
        "id": "yaAxNdnWbYgk4oeZ", # Hashed ID
        "name": "Jane Doe"
    }
]

或参考文档here和示例here

© www.soinside.com 2019 - 2024. All rights reserved.