Недавно я развернул свое веб-приложение Flask на Heroku, но одна из функций, в частности, не работает, как на моем локальном хосте. Функция извлекает информацию о балансе из Yahoo Finance, сохраняет ее в Pandas DataFrame, преобразует ее в HTML и затем отображает на веб-странице. Однако на Heroku, хотя я не получаю никаких ошибок, вся таблица полностью разделена.
Вы также можете попробовать балансовую часть моего приложения по по этой ссылке , если хотите я хотел бы воочию увидеть, что происходит не так. Заранее благодарим!
Python Код:
import requests
import yahoo_fin.stock_info as si
from flask import render_template
def get_balance_sheet(ticker):
try:
def get_symbol(symbol):
url = "http://d.yimg.com/autoc.finance.yahoo.com/autoc?query={}®ion=1&lang=en".format(symbol)
result = requests.get(url).json()
for x in result['ResultSet']['Result']:
if x['symbol'] == symbol:
return x['name']
company_name = get_symbol(ticker.upper())
df = si.get_balance_sheet(ticker)
return render_template('balanceSheetOutput.html', company_name=company_name, tables=[df.to_html(classes='data center table-sortable', index=False)], titles=df.columns.values)
except Exception as e:
return render_template('error.html', e = e)
HTML Код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>TradeView - Balance Sheet</title>
<script src="sort-table.js"></script>
<link rel="stylesheet" href="sort-table.css">
<link rel="stylesheet" href="https://unpkg.com/purecss@2.0.3/build/pure-min.css" integrity="sha384-cg6SkqEOCV1NbJoCu11+bm0NvBRc8IYLRGXkmNrqUBfTjmMYwNKPWBTIKyw9mHNJ" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<style>
table.center {
margin-left:auto;
margin-right:auto;
}
.table-sortable th {
cursor: pointer;
}
.table-sortable .th-sort-asc::after {
content: "\25b4";
}
.table-sortable .th-sort-desc::after {
content: "\25be";
}
.table-sortable .th-sort-asc::after,
.table-sortable .th-sort-desc::after {
margin-left: 5px;
}
.table-sortable .th-sort-asc,
.table-sortable .th-sort-desc {
background: rgba(0, 0, 0, 0.1);
}
table{
width:100%;
}
.tbl-header{
background-color: rgba(255,255,255,0.3);
}
.tbl-content{
height:300px;
overflow-x:auto;
margin-top: 0px;
border: 1px solid rgba(255,255,255,0.3);
}
th{
padding: 20px 15px;
text-align: left;
font-weight: 500;
font-size: 12px;
color: #fff;
text-transform: uppercase;
}
td{
padding: 15px;
text-align: left;
vertical-align:middle;
font-weight: 300;
font-size: 12px;
color: #fff;
border-bottom: solid 1px rgba(255,255,255,0.1);
}
</style>
</head>
<body>
<nav>
<div class="logo">
<a href="{{ url_for('home') }}">
<img src="{{url_for('static', filename='img/logo.png')}}">
</a>
</div>
<div class="hamburger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
<ul class="nav-links">
<li><a class="hover" href="{{ url_for('home') }}">Home</a></li>
<li><a class="hover" href="{{ url_for('stockData') }}">Stock Data</a></li>
<li><a class="hover" href="{{ url_for('recommendations') }}">Recommendations</a></li>
<li><a class="hover" href="{{ url_for('technical_indicators') }}">Technical Indicators</a></li>
<li><a class="hover" href="{{ url_for('contact') }}">Contact</a></li>
<li><a class="hover" href="{{ url_for('about') }}">About</a></li>
<li><button class="login-button" href="#">Login</button></li>
<li><button class="join-button" href="#">Join</button></li>
</ul>
</nav>
<div style="padding-top: 105px;">
<h1 id="title" style="text-align: center;">
Balance Sheet for {{ company_name }}!
</h1>
<div class="tbl-header" style="overflow-x: auto; text-align: center; font-size: 24px;">
{% for table in tables %}
{{titles[loop.index]}}
{{ table|safe }}
{% endfor %}
</div>
<script>
const hamburger = document.querySelector(".hamburger");
const navLinks = document.querySelector(".nav-links");
const links = document.querySelectorAll(".nav-links li");
hamburger.addEventListener('click', ()=>{
//Animate Links
navLinks.classList.toggle("open");
links.forEach(link => {
link.classList.toggle("fade");
});
//Hamburger Animation
hamburger.classList.toggle("toggle");
});
function sortTableByColumn(table, column, asc = true) {
const dirModifier = asc ? 1 : -1;
const tBody = table.tBodies[0];
const rows = Array.from(tBody.querySelectorAll("tr"));
if (column !== 1) {
sortedRows = rows.sort((a, b) => {
const aColText = a.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim();
const bColText = b.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim();
return aColText > bColText ? (1 * dirModifier) : (-1 * dirModifier);
})
}
else {
sortedRows = rows.sort((a, b) => {
const aColPrice = parseFloat(a.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim().replace('$', ''));
const bColPrice = parseFloat(b.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim().replace('$', ''));
return aColPrice > bColPrice ? (1 * dirModifier) : (-1 * dirModifier);
})
}if (column !== 1) {
sortedRows = rows.sort((a, b) => {
const aColText = a.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim();
const bColText = b.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim();
return aColText > bColText ? (1 * dirModifier) : (-1 * dirModifier);
})
}
else {
sortedRows = rows.sort((a, b) => {
const aColPrice = parseFloat(a.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim().replace('$', ''));
const bColPrice = parseFloat(b.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim().replace('$', ''));
return aColPrice > bColPrice ? (1 * dirModifier) : (-1 * dirModifier);
})
}
// Remove all existing TRs from the table
while (tBody.firstChild) {
tBody.removeChild(tBody.firstChild);
}
// Re-add the newly sorted rows
tBody.append(...sortedRows);
// Remember how the column is currently sorted
table.querySelectorAll("th").forEach(th => th.classList.remove("th-sort-asc", "th-sort-desc"));
table.querySelector(`th:nth-child(${ column + 1})`).classList.toggle("th-sort-asc", asc);
table.querySelector(`th:nth-child(${ column + 1})`).classList.toggle("th-sort-desc", !asc);
}
document.querySelectorAll(".table-sortable th").forEach(headerCell => {
headerCell.addEventListener("click", () => {
const tableElement = headerCell.parentElement.parentElement.parentElement;
const headerIndex = Array.prototype.indexOf.call(headerCell.parentElement.children, headerCell);
const currentIsAscending = headerCell.classList.contains("th-sort-asc");
sortTableByColumn(tableElement, headerIndex, !currentIsAscending);
});
});
</script>
<script
src="{{ url_for('static',filename='js/boostraps.js') }}">
</script>
<script
src="{{ url_for('static',filename='js/bootstrap.min.js') }}">
</script>
<script
src="{{ url_for('static',filename='js/main.js') }}">
</script>
<script>
$(window).on("load resize ", function() {
var scrollWidth = $('.tbl-content').width() - $('.tbl-content table').width();
$('.tbl-header').css({'padding-right':scrollWidth});
}).resize();
</script>
</body>
</html>
Скриншоты Imgur: Скриншоты LocalHost Скриншот приложения Heroku