Python / MySQL:只对一次成功写入数据库

时间:2017-04-10 04:41:27

标签: python mysql database python-3.x cs50

慢慢构建我的应用程序(对于CS50)它似乎工作,但只有一次它会写入数据库。我可以访问该网站,下订单,每次都会在HTML页面上成功显示我的订单。但只有一次它会将订单写入数据库并显示它。我可以退出,但仍然只会将一个订单写入数据库。

@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
    if request.method == "POST":
        #http://stackoverflow.com/questions/32640090/python-flask-keeping-track-of-user-sessions-how-to-get-session-cookie-id
        id = session.get('user_id')

        url_start = 'http://download.finance.yahoo.com/d/quotes.csv?s='
        url_middle = request.form["symbol"]
        url_end = '&f=nsl1d1t1c1ohgv&e=.csv'
        full_url = url_start + url_middle + url_end

        # http://stackoverflow.com/questions/21351882/reading-data-from-a-csv-file-online-in-python-3
        response = urllib.request.urlopen(full_url)

        datareader = csv.reader(io.TextIOWrapper(response))
        quote_list = list(datareader)

        num_shares = request.form["num_shares"]

        name = quote_list[0][0]
        symbol = quote_list[0][1]
        price = float(quote_list[0][2])

        #http://stackoverflow.com/questions/12078571/jinja-templates-format-a-float-as-comma-separated-currency
        total_cost = round((float(price) * 100.0) * float(num_shares) / 100.0,2)

        username = db.execute("SELECT username FROM users WHERE id = :id", id=id)
        username = username[0]
        username = username.get('username')

        db.execute("INSERT INTO purchases (id, symbol, name, shares, price, total) VALUES(:id, :symbol, :name, :shares, :price, :total)",
            id=id, symbol=symbol, name=name, price=price, shares=num_shares, total=total_cost)

        return render_template("bought.html", username=username, id=id, name=name, symbol=symbol, price=price, num_shares=num_shares, total_cost=total_cost)
    else:
        return render_template("buy.html")

2 个答案:

答案 0 :(得分:1)

首先,大多数问题都可以通过将函数分成几部分并检查每个部分是否按预期工作来解决,所以让我们稍微重构一下代码。

# additional import for generating URL from parts,
# not by concatenating strings
import urllib.parse


@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
    if request.method != "POST":
        return render_template("buy.html")

    # http://stackoverflow.com/questions/32640090/python-flask-keeping-track-of-user-sessions-how-to-get-session-cookie-id
    user_id = session.get('user_id')

    # what is "full_url"?
    # to which resource and what we get with it?
    full_url = generate_url(symbol=request.form["symbol"])

    # http://stackoverflow.com/questions/21351882/reading-data-from-a-csv-file-online-in-python-3
    response = urllib.request.urlopen(full_url)

    datareader = csv.reader(io.TextIOWrapper(response))
    quote_list = list(datareader)

    num_shares = request.form["num_shares"]

    # what first element means,
    # if it contains info about specific data
    # there should be name for it
    quote_list_first_element = quote_list[0]
    name = quote_list_first_element[0]
    # is this symbol different from one in "request.form"?
    symbol = quote_list_first_element[1]
    price = float(quote_list_first_element[2])

    # http://stackoverflow.com/questions/12078571/jinja-templates-format-a-float-as-comma-separated-currency
    total_cost = get_total_cost(price, num_shares)

    username = fetch_user_name(user_id)

    save_purchase(user_id=user_id,
                  symbol=symbol,
                  name=name,
                  price=price,
                  num_shares=num_shares,
                  total_cost=total_cost)

    return render_template("bought.html",
                           username=username,
                           id=user_id,
                           name=name,
                           symbol=symbol,
                           price=price,
                           num_shares=num_shares,
                           total_cost=total_cost)


def fetch_user_name(user_id):
    username = db.execute("SELECT username FROM users WHERE id = :user_id",
                          user_id=user_id)
    username = username[0]
    username = username.get('username')
    return username


def save_purchase(user_id, name, num_shares,
                  price, symbol, total_cost):
    db.execute(
        "INSERT INTO purchases (id, symbol, name, num_shares, price, total) "
        "VALUES (:user_id, :symbol, :name, :num_shares, :price, :total)",
        # FIXME: if "purchases" table's "id" column is a primary key 
        # here we are saving purchase by user id 
        # not by purchase id (which probably is auto-incremented 
        # and should not be specified in insert query at all), 
        # so for each user we will have only one purchase since primary key is unique
        user_id=user_id,
        symbol=symbol,
        name=name,
        price=price,
        # maybe it will be better to rename column into "num_shares"?
        shares=num_shares,
        # maybe it will be better to rename column into "total_cost"?
        total=total_cost)


def get_total_cost(price, num_shares):
    return round((float(price) * 100.0) * float(num_shares) / 100.0, 2)


def generate_url(symbol):
    scheme = 'http'
    netloc = 'download.finance.yahoo.com'
    path = '/d/quotes.csv'
    params = ''
    # what 's' query parameter means?
    # looks like it stands for "symbol", but which one?
    # is it product label or something else?
    query_dict = dict(s=symbol,
                      f='nsl1d1t1c1ohgv',
                      e='.csv')
    query_str = urllib.parse.urlencode(query_dict)
    fragment = ''
    components = [scheme, netloc, path, params, query_str, fragment]
    return urllib.parse.urlunparse(components)

现在我们可以看到我们按用户ID保存每次购买,但它可能是自动递增的列,或者有用户ID的列,而不是购买ID,我不知道您的数据库架构是什么

如果purchases表的id列自动递增,我们可以删除user_id参数

def save_purchase(name, num_shares,
                  price, symbol, total_cost):
    db.execute(
        "INSERT INTO purchases (symbol, name, num_shares, price, total) "
        "VALUES (:symbol, :name, :num_shares, :price, :total)",
        symbol=symbol,
        name=name,
        price=price,
        shares=num_shares,
        total=total_cost)

如果purchases表同时包含iduser_id列,并且我们要插入指定user_id的记录,则应该像

def save_purchase(user_id, name, num_shares,
                  price, symbol, total_cost):
    db.execute(
        "INSERT INTO purchases (user_id, symbol, name, num_shares, price, total) "
        "VALUES (:user_id, :symbol, :name, :num_shares, :price, :total)",
        user_id=user_id,
        symbol=symbol,
        name=name,
        price=price,
        shares=num_shares,
        total=total_cost)

希望它有所帮助。

答案 1 :(得分:0)

简单回答:我设置的购买表与用户表一样,id_num在两个表中都是唯一的。它应该在用户表中是唯一的,因为用户是唯一的。但它在购买表中不应该是唯一的,因为同一个用户可以进行多次购买。