1

I'd like to allow users to buy and sell shares they already own from the index page. I've created a button for this on the index, and I simply want to send the user to the /buy.html or /sell.html page that I've created - with the share symbol already populated. The index page looks like this:

enter image description here

When I click the BUY button, I send the user to the page below - but I'd like the share symbol pre-populated (e.g. it would say TSLA instead of placeholder ABCD):

enter image description here

I think this boils down to two questions:(i) how do i send the right information back to application.py; (ii) what html attribute/setting do I need to use to pre-populate the symbol field in the buy.html form - rather than simply having it as a placeholder?

The relevant part of index.html is:

{% extends "layout.html" %}

{% block title %}
    Portfolio
{% endblock %}

{% block main %}
    <table>    
        <tr>
            <th>Symbol</th>
            <th>Name</th>
            <th>Number of Shares Owned</th>
            <th>Total Amount Paid ($US)</th>
            <th>Current Value ($US)</th>
            <th>Gain/(Loss) ($US)</th>
            <th>Options</th>
    </tr>

    {% for share in shares_owned %}
        {% if share.num_shares_owned > 0 %}
        <tr>
            <td>{{share.symbol}}</td>
            <td>{{share.name}}</td>
            <td>{{share.num_shares_owned}}</td>
            <td>{{share.total_cost_usd}}</td>
            <td>{{share.total_asset_value_usd}}</td>
            <td>{{share.gain_loss_usd}}</td>
            <td>
                <div class="form-group">
                    <button class="btn btn-default" type="submit"><a href="{{ url_for('buy', symbol ='{{share.symbol}}')}}">Buy</a></button>
                    <button class="btn btn-default" type="submit"><a href="{{ url_for('sell', symbol ='{{share.symbol}}')}}">Sell</a></button>
                </div>
            </td>
        </tr>
        {% endif %}
    {% endfor %}
    [THE REST OF THE HTML CODE]
{% endblock %}

The relevant bit of my code for buy() in application.py is:

@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
    """Buy shares of stock."""

    # if user reached route via POST (as by submitting a form via POST)
    if request.method == "POST":
        # THE BUY() METHOD

    # else if user reached route via GET (as by clicking a link or via redirect)
    else:
        # if user reached route via GET from index - and hence is asking to buy more shares in a company he/she already owns
        temp_symbol = request.form.get("symbol")
        if temp_symbol is not None:
            # Declare a dict called "temp"
            temp = {}
            # Add symbol to this dict
            temp["symbol"] = temp_symbol

        else:
        # otherwise add "ABCD" to the dict (this will then be displayed as the placeholder)
            temp = {}
            temp["symbol"] = "ABCD"

        return render_template("buy.html", temp = temp)

My understanding is that request.form.get("symbol") is returning None - but I don't understand why, since I thought I'd set it up in index.html such that it would return share.symbol.

I'd appreciate any help you can give!

Many thanks, Matt

2
  • You ask some interesting questions, thanks Jul 1 '17 at 19:34
  • My pleasure! Hope it's helpful. Jul 3 '17 at 16:58
2
  • The "something like" syntax in this call for the href attribute was wrong and has been corrected. It is more something like href="{{ url_for('buy', symbol=stock.symbol ) }}". stock.symbol should not be quoted nor escaped with braces. (the quotes make it a literal; the braces are only used to escape the objects from html).
  • An a element cannot be a descendant of a button element. Use an a element with the same class as the button for styling.
  • When using a GET request, the query values are not in request.form, which explains why request.form.get("symbol") returns None. Use request.args. From the flask doc:

To access parameters submitted in the URL (?key=value) you can use the args attribute:

searchword = request.args.get('key', '')

  • In buy.html, you can use the value attribute for the symbol field to set the "default" as the symbol that was send in the render_template call. Something like value="{{temp.symbol}}".

Addendum after comment:

Here's what I would do: send the whole value attribute as an argument to buy.html. Something like

if not request.args.get("symbol"):
    val=""
else:
   val='value=' + request.args.get("symbol")

Then in buy.html add {{val}} to the input tag (ie instead of value=... ). (I tried it and it worked in Firefox, the html is valid).

I suspect the / is coming from the tag close ('/>'). Move the value attribute and it will display whatever follows it.

3
  • Thanks! Using the args attribute works, along with the value attribute (in the html). I've still got a problem though. I've tried using this code in the html: placeholder="ABCD" type="text" value={{temp.symbol|default ("", true). Result is that if you get to buy via GET (in which case temp.symbol is None) the Enter Share Symbol box in buy.html has value "/" in the box - rather than having a placeholder "ABCD". One solution would be to create a whole different html page (buy2.html) for cases where the user reaches buy via GET. But this seems really inelegant and inefficient. Any thoughts? Tx! Jul 3 '17 at 16:57
  • Added info to the answer (to difficult to "think" in a comment :). Jul 4 '17 at 4:04
  • Thanks so much! I've been away on holiday, and it was great to get this when I got back! Jul 18 '17 at 19:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .