Django上下文处理器报错:'NoneType' object is not iterable 求助
上下文处理器报错'NoneType' object is not iterable的排查与解决
问题场景
我想通过上下文处理器在所有模板中显示借款请求通知消息,但运行时触发错误:'NoneType' object is not iterable,无法自行解决,相关代码如下:
上下文处理器代码(context_processors.py)
from django.contrib import messages from .models import Loan def message_notification(request): loan_requested_lists = Loan.objects.filter(loan_req_user=request.user, active=True, status='Pending') if loan_requested_lists.exists(): if loan_requested_lists.count() == 1: for i in loan_requested_lists: return messages.info(request, f'{i.user.username}({i.user.account_number}) was requested for loan.') else: return messages.info(request, f'{loan_requested_lists.count()} users were requested for loan.')
模型代码(models.py)
from django.utils import timezone from django.db import models from accounts.models import User from django.core.exceptions import ValidationError STATUS = ( ('Pending', 'Pending'), ('Accepted', 'Accepted') ) EDITABLE_STATUS = ( ('Not Applicable', 'Not Applicable'), ('Requested', 'Requested'), ('Approved', 'Approved'), ('Not Approved', 'Not Approved'), ('Updated', 'Updated'), ) def validate_date(date): if date < timezone.now(): raise ValidationError("Date cannot be in the past") class Loan(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) loan_req_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='loan_given_user_list', verbose_name='Loan Requested From User') amount = models.PositiveIntegerField(verbose_name='Loan Amount') date = models.DateTimeField(default=timezone.now, validators=[validate_date], verbose_name='Loan Return Date') status = models.CharField(max_length=8, choices=STATUS, default='Pending') editable = models.CharField(max_length=14, choices=EDITABLE_STATUS, default='Not Applicable') active = models.BooleanField(default=True) created = models.DateTimeField(auto_now_add=True, verbose_name='Loan Requested Date') def __str__(self): return self.user.username
错误原因
- 上下文处理器返回值错误:Django要求上下文处理器必须返回一个字典,而当前代码返回的是
messages.info()的执行结果(该方法返回None),Django尝试迭代这个None值时就会触发*'NoneType' object is not iterable*错误。 - 未处理未登录用户场景:当用户未登录时,
request.user是AnonymousUser,直接用它作为查询条件可能引发异常,进一步加剧问题。
修复方案
修改上下文处理器,确保返回字典,同时处理未登录用户的情况,正确使用消息框架添加通知:
# 修改后的context_processors.py from django.contrib import messages from .models import Loan def message_notification(request): # 先判断用户是否已登录,未登录直接返回空字典 if not request.user.is_authenticated: return {} loan_requested_lists = Loan.objects.filter(loan_req_user=request.user, active=True, status='Pending') if loan_requested_lists.exists(): count = loan_requested_lists.count() if count == 1: # 取第一条数据,避免不必要的循环 loan = loan_requested_lists.first() messages.info(request, f'{loan.user.username}({loan.user.account_number}) 向您发起了借款请求。') else: messages.info(request, f'共有{count}位用户向您发起了借款请求。') # 上下文处理器必须返回字典,即使是空字典 return {}
关键说明
- 上下文处理器的核心职责是向模板上下文添加数据,必须返回字典,不能返回其他类型。
- Django的消息框架会自动将添加的消息存储到用户会话中,模板中只需通过
{% if messages %}标签遍历显示即可,无需在上下文处理器中传递消息列表。 - 必须处理用户未登录的情况,避免匿名用户触发查询错误。
内容的提问来源于stack exchange,提问作者Evan
相关产品推荐
相关产品推荐

