当对象的类型不是None

时间:2019-07-19 21:30:39

标签: python django

我正在尝试制作一个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'

Error in browser

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>

1 个答案:

答案 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_requestNone(导致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

中的环境对其进行定义。