我正在尝试制作一个Django应用程序,该应用程序允许查看客户的所有财务投资组合(在这种情况下,是各种股票,共同基金和“其他”,例如401k)
我在我的views.py文件中创建了一个由客户过滤的共同基金查询集,我试图将其传递给html模板并呈现该列表。我遇到标题错误,但是:'NoneType'对象没有属性'get'。
我已经通过打印语句验证了QuerySet是 not 类型的None,并且当我将其存储在视图中的变量中时,我要使用的所有数据均已正确返回。
我拥有适用于股票的所有产品,并且它具有相同的功能,可以很好地工作,因此我无法弄清两者之间的区别,以及为什么一个起作用而另一个却不起作用。是什么导致此错误?
下面是我认为直接相关的代码块和错误消息。完整代码位于:https://github.com/apalmesano2/assignment2_part2
错误
Internal Server Error: /customer/2/portfolio/
Traceback (most recent call last):
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
return view_func(request, *args, **kwargs)
File "C:\Users\andre\isqa8380\efsd-local\efs\portfolio\views.py", line 270, in portfolio
'mutual_funds': mutual_funds,
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\shortcuts.py", line 36, in render
content = loader.render_to_string(template_name, context, request, using=using)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\loader.py", line 62, in render_to_string
return template.render(context, request)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\backends\django.py", line 61, in render
return self.template.render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 175, in render
return self._render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 167, in _render
return self.nodelist.render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 943, in render
bit = node.render_annotated(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 910, in render_annotated
return self.render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\loader_tags.py", line 155, in render
return compiled_parent._render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 167, in _render
return self.nodelist.render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 943, in render
bit = node.render_annotated(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 910, in render_annotated
return self.render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\loader_tags.py", line 67, in render
result = block.nodelist.render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 943, in render
bit = node.render_annotated(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 910, in render_annotated
return self.render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\defaulttags.py", line 211, in render
nodelist.append(node.render_annotated(context))
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 910, in render_annotated
return self.render(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 993, in render
output = self.filter_expression.resolve(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 676, in resolve
obj = self.var.resolve(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 802, in resolve
value = self._resolve_lookup(context)
File "C:\Users\andre\isqa8380\efsd-local\lib\site-packages\django\template\base.py", line 864, in _resolve_lookup
current = current()
File "C:\Users\andre\isqa8380\efsd-local\efs\portfolio\models.py", line 114, in current_mutual_fund_price
mf_open_price = float(mf_json_data.get('Global Quote').get('05. price'))
AttributeError: 'NoneType' object has no attribute 'get'
models.py
class Stock(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='stocks')
symbol = models.CharField(max_length=10)
name = models.CharField(max_length=50)
shares = models.DecimalField(max_digits=10, decimal_places=1)
purchase_price = models.DecimalField(max_digits=10, decimal_places=2)
purchase_date = models.DateField(default=timezone.now, blank=True, null=True)
def created(self):
self.recent_date = timezone.now()
self.save()
def __str__(self):
return str(self.customer)
def initial_stock_value(self):
return self.shares * self.purchase_price
def current_stock_price(self):
symbol_f = str(self.symbol)
main_api = 'https://www.alphavantage.co/query?function=BATCH_STOCK_QUOTES&symbols='
api_key = '&apikey= <MY_API_KEY>'
url = main_api + symbol_f + api_key
json_data = requests.get(url).json()
open_price = float(json_data["Stock Quotes"][0]["2. price"])
share_value = open_price
return share_value
def current_stock_value(self):
return round((Decimal(self.current_stock_price()) * Decimal(self.shares)), 3)
class MutualFund(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='mutual_funds')
symbol = models.CharField(max_length=10)
name = models.CharField(max_length=50)
shares = models.DecimalField(max_digits=10, decimal_places=1)
purchase_price = models.DecimalField(max_digits=10, decimal_places=2)
purchase_date = models.DateField(default=timezone.now, blank=True, null=True)
def created(self):
self.recent_date = timezone.now()
self.save()
def __str__(self):
return str(self.customer)
def initial_mutual_fund_value(self):
return self.shares * self.purchase_price
def current_mutual_fund_price(self):
mf_symbol_f = str(self.symbol)
mf_main_api = 'https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol='
mf_api_key = '&apikey= <MY_API_KEY>'
mf_url = mf_main_api + mf_symbol_f + mf_api_key
mf_json_data = requests.get(mf_url).json()
mf_open_price = float(mf_json_data.get('Global Quote').get('05. price'))
mf_share_value = mf_open_price
return mf_share_value
def current_mutual_fund_value(self):
return round((Decimal(self.current_mutual_fund_price()) * Decimal(self.shares)), 3)
views.py
def portfolio(request, pk):
customer = get_object_or_404(Customer, pk=pk)
customers = Customer.objects.filter(created_date__lte=timezone.now())
investments = Investment.objects.filter(customer=pk)
stocks = Stock.objects.filter(customer=pk)
mutual_funds = MutualFund.objects.filter(customer=pk)
sum_recent_value = Investment.objects.filter(customer=pk).aggregate(Sum('recent_value'))
sum_acquired_value = Investment.objects.filter(customer=pk).aggregate(Sum('acquired_value'))
# overall_investment_results = sum_recent_value-sum_acquired_value
# Initialize the value of the stocks
sum_current_stocks_value = 0
sum_of_initial_stock_value = 0
sum_current_mutual_fund_value = 0
sum_initial_mutual_fund_value = 0
# Loop through each stock and add the value to the total
for stock in stocks:
sum_current_stocks_value += stock.current_stock_value()
sum_of_initial_stock_value += stock.initial_stock_value()
for mutual_fund in mutual_funds:
sum_current_mutual_fund_value += mutual_fund.current_mutual_fund_value()
sum_initial_mutual_fund_value += mutual_fund.initial_mutual_fund_value()
sum_recent_investments = sum_recent_value.get('recent_value__sum')
sum_acquired_investments = sum_acquired_value.get('acquired_value__sum')
portfolio_initial_total = sum_of_initial_stock_value + sum_initial_mutual_fund_value + sum_acquired_investments
portfolio_current_total = sum_current_stocks_value + sum_current_mutual_fund_value + sum_recent_investments
return render(request, 'portfolio/portfolio.html', {'customers': customers,
'investments': investments,
'stocks': stocks,
'sum_acquired_value': sum_acquired_value,
'sum_recent_value': sum_recent_value,
'sum_current_stocks_value': sum_current_stocks_value,
'sum_of_initial_stock_value': sum_of_initial_stock_value,
'portfolio_initial_total': portfolio_initial_total,
'portfolio_current_total': portfolio_current_total,
'sum_recent_investments': sum_recent_investments,
'sum_acquired_investments': sum_acquired_investments,
'sum_current_mutual_fund_value': sum_current_mutual_fund_value,
'sum_initial_mutual_fund_value': sum_initial_mutual_fund_value,
'mutual_funds': mutual_funds,
})
portfolio.html
<div class="row">
<h2 style="padding-left: 15Px">Mutual Fund Information</h2>
</div>
<div class="row">
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="bg-info">
<th>Customer</th>
<th>Symbol</th>
<th>Name</th>
<th>Shares</th>
<th>Initial Mutual Fund Price</th>
<th>Initial Mutual Fund Value</th>
<th>Current Mutual Fund Price</th>
<th>Current Mutual Fund Value</th>
<th>Results</th>
</tr>
</thead>
<tbody>
{% for mutual_fund in mutual_funds %}
<tr>
<td>{{ mutual_fund.customer }}</td>
<td>{{ mutual_fund.symbol }}</td>
<td>{{ mutual_fund.name }}</td>
<td>{{ mutual_fund.shares|intcomma }}</td>
<td>{{ mutual_fund.purchase_price|intcomma }}</td>
<td>{{ mutual_fund.initial_mutual_fund_value|intcomma }}</td>
<td>{{ mutual_fund.current_mutual_fund_price|intcomma }}</td>
<<td>{{ mutual_fund.current_mutual_fund_value|intcomma }}</td>
<td>{{ mutual_fund.current_mutual_fund_value|sub:mutual_fund.initial_mutual_fund_value|intcomma }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr class="bg-info">
<th>Total of Initial Mutual Funds</th>
<th>Total of Current Mutual Funds</th>
<th>Results</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ sum_initial_mutual_fund_value|intcomma }}</td>
<td>{{ sum_current_mutual_fund_value|intcomma }}</td>
<td>{{ sum_current_mutual_fund_value|sub:sum_initial_mutual_fund_value|intcomma }}</td>
</tr>
</tbody>
</table>
</div>
答案 0 :(得分:0)
欢迎使用StackOverflow!
似乎您的变量:mf_json_data
在以下位置定义:https://github.com/apalmesano2/assignment2_part2/blob/master/portfolio/models.py#L113返回值失败,结果为mf_request = None
。
我建议您确保您的mf_json_data = requests.get(mf_url).json()
正在适当拉动。
尝试使用以下方法进行调试:
mf_request = requests.get(mf_url)
print('MF Request:', mf_request, 'MF Request Type: ', type(mf_request))
if mf_request.status_code != 200:
print('Bad request')
return 'Unavailable'
mf_json_data = mf_request.json()
无论如何,由于您的mf_request
为None
(导致NoneType
异常)而发生了错误。
编辑:根据您的评论以及返回值,我想说您应该处理.get('Global Quote')
返回为None
的情况。
尝试这样的事情:
def current_mutual_fund_price(self):
mf_symbol_f = str(self.symbol)
mf_main_api = 'https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol='
mf_api_key = '&apikey=REDACTED'
mf_url = mf_main_api + mf_symbol_f + mf_api_key
mf_json_data = requests.get(mf_url).json()
mf_open_price = float(mf_json_data.get('Global Quote', {}).get('05. price', 0))
mf_share_value = mf_open_price
return mf_share_value
相关更新为:
mf_open_price = float(mf_json_data.get('Global Quote', {}).get('05. price', 0))
很显然,您需要使用合理的默认值或(如果值为false)来更新.get('05.price', 0)
中的默认值。
一旦对此进行了更新,就不会再收到该错误,但是您将需要处理找不到任何值的情况。
但这是根据您的问题进行的推测。
此外,我建议您从Github中删除您的秘密。
您将要旋转在https://github.com/apalmesano2/assignment2_part2/blob/master/portfolio/models.py#L111处定义的机密,并可能通过settings.py