【问题标题】:'NoneType' object has no attribute 'get' when the object is not type None [closed]当对象不是无类型时,“NoneType”对象没有属性“get”[关闭]
【发布时间】:2019-11-28 21:08:01
【问题描述】:

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

【问题讨论】:

  • 修复你的缩进,提供一个驱动程序来引发错误,并给我们整个错误信息——包括回溯。删除多余的代码和数据。 那么我们有一个很好的起点来寻找问题。

标签: python django


【解决方案1】:

欢迎来到 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))

显然,您需要使用合理的默认值更新.get('05.price', 0)中的默认值,如果该值为falsey。

更新此内容后,您应该不会再收到错误消息,但您需要处理未找到值的情况。

不过,根据您的问题,这是相当推测的。

另外,我建议你从 Github 上编辑你的秘密。

您需要轮换在 https://github.com/apalmesano2/assignment2_part2/blob/master/portfolio/models.py#L111 中定义的秘密,并可能通过 settings.py 中的环境定义它

【讨论】:

  • 如果变量没有返回任何东西,我是否有理由打印出变量的返回值?我得到以下信息:mf_json_data {'Global Quote': {'01. symbol': 'TPLGX', '02. open': '46.9200', '03. high': '46.9200', '04. low': '46.9200', '05. price': '46.9200', '06. volume': '0', '07. latest trading day': '2019-07-18', '08. previous close': '46.9500', '09. change': '-0.0300', '10. change percent': '-0.0639%'}}
  • @Andrew 我已经通过相关更改更新了我的答案。您需要处理价格为 0 或您在模板和后端逻辑中决定的任何合理默认值的情况。
  • 谢谢你修复它!现在我只需要弄清楚如何减少我的 API 调用次数并仍然获得相同的数据,因为我使用的是免费版本哈哈
猜你喜欢
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 2022-08-10
  • 2016-09-20
  • 2019-05-21
  • 1970-01-01
  • 2021-08-03
相关资源
最近更新 更多