首页 > 解决方案 > 缺少参数的烧瓶返回重定向(url_for)错误

问题描述

我有以下代码,当我尝试使用return redirect(url_for)andpresent函数时,future我收到以下错误消息:

类型错误:home() 缺少 1 个必需的位置参数:'calc_type'

我尝试了多种方法将calc_type变量传递给home函数并且总是得到相同的错误。任何帮助表示赞赏。

from flask import render_template, redirect, url_for, request
from app import app, db
from models import Pres, Future

@app.route('/home')
def home(calc_type):
    if (calc_type == "present"):
        try:
            inputs = Pres.query.all()
            for item in inputs:
                cash = item.cash
                rate = item.rate
                periods = item.periods
            pv = cash / (1 + rate)**periods
            return render_template('present.html', inputs=inputs, cash=cash, pv=pv)
        except:
            return render_template('present.html')
    elif (calc_type == "future"):
        inputs = Future.query.all()
        for item in inputs:
            cash = item.cash
            rate = item.rate
            periods = item.periods
        fv = cash * (1 + rate)**periods
        return render_template('present.html', inputs=inputs, cash=cash, fv=fv)

@app.route('/present', methods=['GET', 'POST'])
def present():
    input = Pres(request.form['cash'], request.form['rate'], request.form['periods'])
    calc_type = "present"
    db.session.add(input)
    db.session.commit()
    return redirect(url_for('home', calc_type=calc_type))

@app.route('/future', methods=['GET', 'POST'])
def future():
    input = Future(request.form['cash'], request.form['rate'], request.form['periods'])
    calc_type = "future"
    db.session.add(input)
    db.session.commit()
    return redirect(url_for('home', calc_type=calc_type))

标签: redirectflaskurl-for

解决方案


按照您的home()看法,它无法接收参数,url_to因为路由路径中没有这样的变量。

视图函数由烧瓶包装,其行为与常规函数不同。对于要接收变量的主视图,您必须在其路由路径中使用变量定义它:

@app.route('/home/<string:calc_type>')
def home(calc_type):
   ...

# Result:
>>> url_for('route', calc_type='present')
'/home/present'

或者,您可以将其作为 url 查询变量传递:

@app.route('/home')
def home():
   calc_type = request.args.get('calc_type')

# Result:
>>> url_for('route', calc_type='present')
'/home?calc_type=present'

但最重要的是,您还应该尝试将视图/路由逻辑与其他代码分开,并尽可能保持视图简洁。

这里有两种方法可以解决这个问题:

选项1

PS:我不会这样做,但最接近您的代码。

def get_view(calc_type):
    if (calc_type == "present"):
        try:
            inputs = Pres.query.all()
            for item in inputs:
                cash = item.cash
                rate = item.rate
                periods = item.periods
            pv = cash / (1 + rate)**periods
            return render_template('present.html', inputs=inputs, cash=cash, pv=pv)
        except:
            return render_template('present.html')
    elif (calc_type == "future"):
        inputs = Future.query.all()
        for item in inputs:
            cash = item.cash
            rate = item.rate
            periods = item.periods
        fv = cash * (1 + rate)**periods
        return render_template('present.html', inputs=inputs, cash=cash, fv=fv)


@app.route('/present', methods=['GET', 'POST'])
def present():
    input = Pres(request.form['cash'], request.form['rate'], request.form['periods'])
    calc_type = "present"
    db.session.add(input)
    db.session.commit()
    return get_view(calc_type)

@app.route('/future', methods=['GET', 'POST'])
def future():
    input = Future(request.form['cash'], request.form['rate'], request.form['periods'])
    calc_type = "future"
    db.session.add(input)
    db.session.commit()
    return get_view(calc_type)

选项 2

# calculations.py
from models import Pres, Future

def present_calc():
    try:
        inputs = Pres.query.all()
        for item in inputs:
            cash = item.cash
            rate = item.rate
            periods = item.periods
        pv = cash / (1 + rate)**periods
        return dict(inputs=inputs, cash=cash, pv=pv)
    except:
        return dict()

def future_calc():
    inputs = Future.query.all()
    for item in inputs:
        cash = item.cash
        rate = item.rate
        periods = item.periods
    fv = cash * (1 + rate)**periods
    return dict(inputs=inputs, cash=cash, fv=fv)


# views.py
from flask import render_template, redirect, url_for, request
from app import app, db

from .calculations import present_calc, future_calc
from app import db



@app.route('/present', methods=['GET', 'POST'])
def present():
    inputs = Pres(
        cash=request.form['cash'],
        rate=request.form['rate'],
        periods=request.form['rate'])
    db.session.add(inputs)
    db.session.commit()

    calcs = present_calc()
    return render_template('present.html', **calcs)

@app.route('/future', methods=['GET', 'POST'])
def future():
    inputs = Pres(
        cash=request.form['cash'],
        rate=request.form['rate'],
        periods=request.form['rate'])
    db.session.add(inputs)
    db.session.commit()

    calcs = future_calc()
    return render_template('future.html', **calcs)

推荐阅读