---
# System prepended metadata

title: Python + Flask 虛擬美國股票交易網站 Part3 （模板/ 模板上下文）
tags: [Flask, CS50, Python]

---

<style>

html, body, .ui-content {
    background-color: #333;
    color: #ddd;
}

body > .ui-infobar {
    display: none;
}

.ui-view-area > .ui-infobar {
    display: block;
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
    color: #ddd;
}

.markdown-body h1,
.markdown-body h2 {
    border-bottom-color: #ffffff69;
}

.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
    color: #fff;
}

.markdown-body img {
    background-color: transparent;
}

.ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a {
    color: white;
    border-left: 2px solid white;
}

.expand-toggle:hover, 
.expand-toggle:focus, 
.back-to-top:hover, 
.back-to-top:focus, 
.go-to-bottom:hover, 
.go-to-bottom:focus {
    color: white;
}


.ui-toc-dropdown {
    background-color: #333;
}

.ui-toc-label.btn {
    background-color: #191919;
    color: white;
}

.ui-toc-dropdown .nav>li>a:focus, 
.ui-toc-dropdown .nav>li>a:hover {
    color: white;
    border-left: 1px solid white;
}

.markdown-body blockquote {
    color: #bcbcbc;
}

.markdown-body table tr {
    background-color: #5f5f5f;
}

.markdown-body table tr:nth-child(2n) {
    background-color: #4f4f4f;
}

.markdown-body code,
.markdown-body tt {
    color: #eee;
    background-color: rgba(230, 230, 230, 0.36);
}

a,
.open-files-container li.selected a {
    color: #5EB7E0;
}


</style>}
# Python + Flask 虛擬美國股票交易網站 Part3 （模板/ 模板上下文）
###### tags: `CS50` `Python` `Flask`


## 前言

網站首頁左側2/3為主體，顯示用戶個資，持股清單。右側1/3為邊欄，顯示用戶的觀察清單。因為不是每個頁面都會顯示觀察清單，因此將觀察清單放在局部模板__sidebar.html中。其餘的寫在基模板base.html中

### vfinance/templates/base.html 程式碼
```
{% from 'bootstrap/nav.html' import render_nav_item %}
<!DOCTYPE html>

<html lang="en">

<head>

    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- documentation at http://getbootstrap.com/docs/4.1/, alternative themes at https://bootswatch.com/ -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">

    <!-- https://favicon.io/emoji-favicons/money-mouth-face/ -->
    <link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}">

    <!-- css sheet -->
    <link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}" type ='text/css'>

    <title>C$50 Finance: {% block title %}{% endblock %}</title>

</head>

<body>
{% block nav %}
    <nav class="navbar navbar-expand-md navbar-light bg-light border">
        <div class="container">

            <!-- navbar brand -->
            <a class="navbar-brand" href="/"><span class="blue">C</span><span class="red">$</span><span class="yellow">5</span><span class="green">0</span> <span class="red">Finance</span></a>
            
            <!-- Hambuger Button -->
            <button aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#navbar" data-toggle="collapse" type="button">
                <span class="navbar-toggler-icon"></span>
            </button>

            {% if current_user.is_authenticated %}
            <div class="collapse navbar-collapse">
                <ul class= 'nav navbar-nav mr-auto'>
                    
                    <li class = 'nav-item dropdown'>
                        <a href="#" class='nav-link dropdown-toggle' data-toggle='dropdown' role = 'button' aria-haspopup='true' area-expanded='false'>
                        My Account <span class='caret'></span>
                        </a>
                        <div class='dropdown-menu' aria-labelledby='navbarDropdown'>
                            <a class='dropdown-item' href = "/">Portifolio</a>
                            <a class='dropdown-item' href = "{{ url_for('admin.trade_history')}}">History</a>
                            <a class='dropdown-item' href = "{{ url_for('admin.show_watchlist')}}">Watchlist</a>     
                        </div>
                    </li>
                    <li class = 'nav-item dropdown'>
                        <a href="#" class='nav-link dropdown-toggle' data-toggle='dropdown' role = 'button' aria-haspopup='true' area-expanded='false'>
                        Trade <span class='caret'></span>
                        </a>
                        <div class='dropdown-menu' aria-labelledby='navbarDropdown'>
                            <a class='dropdown-item' href = "{{ url_for('admin.get_quote')}}">Buy</a>
                            <a class='dropdown-item' href = "#">Sell</a>
                            
                        </div>
                    </li>
                    <li class = 'nav-item dropdown'>
                        <a href="#" class='nav-link dropdown-toggle' data-toggle='dropdown' role = 'button' aria-haspopup='true' area-expanded='false'>
                        BackTest <span class='caret'></span>
                        </a>
                    </li>
                    
                    
                </ul>

            </div>
            <div class="navbar-collapse collapse ">
                
                <ul class="navbar-nav ml-auto">
                    <form class="form-inline my-2 my-lg-0" method = 'post'
                        action="{{ url_for('admin.get_quote') }}">
                        {% if form %}
                        {{form.csrf_token}}    
                        {% endif %}
                        

                    <input class="form-control mr-sm-2" type="search" placeholder="Search"  aria-label="Search" id ='symbol' name = 'symbol'>
                    <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Quote</button>
                    </form>
                    <li class="nav-item">
                        <a class="nav-link" href="#">{{ current_user.username }}</a>
                    </li> 
                    <li class="nav-item">
                        <a class="nav-link" href="{{ url_for('auth.logout', next = request.full_path) }}">logout</a>
                    </li>             
                </ul>
            </div>
            {% else %}
            <div class="collapse navbar-collapse">           
                <ul class="nav navbar-nav navbar-right">
                    {{ render_nav_item('auth.register', "Register") }}
                    {{ render_nav_item('auth.login', "Login") }}
                </ul>
            </div>
            {% endif %}


        </div>
    </nav>
{% endblock nav %}    
<main class="container p-5">
    {% for message in get_flashed_messages(with_categories=True) %}
    <div class="alert alert-{{ message[0]}}" role='alert'>
        <button type="button" class="close" data-dismiss="alert">&times;</button>
        {{ message[1]}}
    </div>

    {% endfor %}

    
        {% block content %}{% endblock %}
    
    <footer class="small text-center text-muted">
        Data provided for free by <a href="https://iextrading.com/developer">IEX</a>. View <a href="https://iextrading.com/api-exhibit-a/">IEX’s Terms of Use</a>.
    </footer>

</main>

{% block scripts %} 
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery-3.2.1.slim.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/popper.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/script.js') }}"></script>
{{ moment.include_moment(local_js=url_for('static', filename='js/moment-with-locales.min.js')) }}
{% endblock scripts %}  




</body>
</html>

```
## 註冊模板上下文 __init __.py

將template中會需要用到的模板註冊到工廠函數中
```


def register_template_context(app):
    @app.context_processor
    def make_template_context():
        user = User.query.first()
        if current_user.is_authenticated:
            watchlist = Watchlist.query.with_parent(current_user).order_by(Watchlist.symbol.asc()).all()
            priceInWatchlist = []
            for stock in watchlist:
                quote = lookup(stock.symbol)
                price = quote['price']
                priceInWatchlist.append(price)


            return dict(
                user = user,
                watchlist = watchlist,
                priceInWatchlist = priceInWatchlist
                
            )
        else:
            return dict(user = user,)


```

## 願望清單模板 vfinance/templates/home/__sidebar.html

```
{% if watchlist %}

<div class='row'>
    <div class="card mb-6">
        <div class="card-header">Watchlist</div>
        <ul class="list-group list-group-flush">
            {% for n in range(watchlist|length) %}
                <li class="list-group-item  list-group-item-action d-flex justify-content-between align-items-center">
                    <a href="{{ url_for('admin.show_quote', symbol = watchlist[n].symbol)}}">
                        {{ watchlist[n].symbol}}
                    </a>
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <a>
                        {{ priceInWatchlist[n] }}
                    </a>
                    
                </li>
                
            {% endfor %}
        </ul>
    </div>
</div>

{% endif %}
```