本来在 HTML 中可以直接调用后端的 url_for 的,比如:
<script>
    var url = "{{ url_for('site.index') }}";
</script>
不过如果是外部引用的 js 的话,就没办法(除非以 HTML data 属性作为中介进行传递,但略麻烦),所以就写了个前端的 urlFor,和后端的 url_for 对应。
首先在后端加入这一段代码:
rules = {}
for endpoint, _rules in iteritems(app.url_map._rules_by_endpoint):
    if any(item in endpoint for item in ['_debug_toolbar', 'debugtoolbar', 'static']):
        continue
    rules[endpoint] = [{'rule': rule.rule} for rule in _rules]
app.jinja_env.globals.update({
    'rules': rules,
})
然后在前端加入以下代码:
// Find out params in routing rules
var pattern = new RegExp("<[^:]*:?([^>]+)>", "g");
var result = null;
$.each(g.rules, function (endpoint, rules) {
    $.each(rules, function (index, rule) {
        rule.params = [];
        while ((result = pattern.exec(rule.rule)) !== null) {
            rule.params.push(result[1]);
        }
    });
});
/**
 * Check whether str ends with suffix.
 * @param str
 * @param suffix
 * @returns {boolean}
 */
function endsWith(str, suffix) {
    return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
/**
 * Generate url for the endpoint.
 * urlFor(endpoint [, parameters])
 * @param endpoint
 * @param parameters
 * @returns url for the endpoint.
 */
function urlFor(endpoint, parameters) {
    var url = null,
        params = [],
        maxMatchDegree = 0.0,
        keys;
    parameters = ($.type(parameters) !== 'undefined') ? parameters : {};
    if (g.rules[endpoint] === undefined) {
        throw new Error("Uncorrect endpoint in " + "urlFor(\"" + endpoint + "\", " +
            JSON.stringify(parameters) + ")");
    }
    keys = $.map(parameters, function (value, key) {
        return key;
    });
    // Find the first matched rule among rules in this endpoint.
    $.each(g.rules[endpoint], function (index, rule) {
        var match = true,
            currentMatchDegree = 0.0;
        $.each(rule.params, function (index, param) {
            if ($.inArray(param, keys) === -1) {
                match = false;
                return false;
            }
        });
        if (match) {
            currentMatchDegree = parseFloat(rule.params.length) / keys.length;
            if (currentMatchDegree > maxMatchDegree || url === null) {
                maxMatchDegree = currentMatchDegree;
                url = rule.rule;
                params = rule.params;
            }
        }
    });
    if (url) {
        $.each(keys, function (index, key) {
            // Build in params
            if ($.inArray(key, params) > -1) {
                url = url.replace(new RegExp("<[^:]*:?" + key + ">"), parameters[key]);
            } else {
                // Query string params
                if (url.indexOf("?") === -1) {
                    url += "?";
                }
                if (!endsWith(url, '?')) {
                    url += "&";
                }
                url += key + "=" + parameters[key];
            }
        });
    } else {
        throw new Error("Uncorrect parameters in urlFor(\"" + endpoint + "\", " +
            JSON.stringify(parameters) + ")");
    }
    return url;
}
使用方法:
url_for('site.index')  →  '/'
url_for('user.view', {uid: 1})  →  '/user/1'
url_for('user.view', {uid: 1, other:'other'})  →  '/user/1?other=other'
url_for('user.view', {other: 'other'})  →  Uncorrect parameters in urlFor("user.view", {other:'other'})
|  |      1hustlzp OP 漏了一个地方,需要提将 rules 赋予 JS 全局变量 g 中: <script> g.rules = {{ rules|safe }}; </script> | 
|  |      2dagger      2015-07-16 21:26:35 +08:00 重度flask瘾患者啊~ 话说这是直接把py翻译到js的吗? |