Django关联字段报错:'NoneType' object has no attribute 'userprofile'
解决Django关联查询报错:'NoneType' object has no attribute 'userprofile'
问题根源
报错指向latest_successful_record.users.first().userprofile.user_nickname,核心原因有两个:
- 当前
Display_Data记录的users关联集合为空,调用first()返回None,后续访问userprofile触发报错 - 存在关联的
User对象,但该用户没有对应的UserProfile实例(OneToOneField未配置自动创建逻辑)
修复步骤
1. 增加空值防护,避免链式调用崩溃
修改视图代码,逐层检查对象是否存在,不要直接链式访问,同时修正原代码中循环内提前返回的错误:
def check_url_exists_and_person(url_to_check): user_info_array = [] for i in range(1, 6): latest_successful_record = Display_Data.objects.filter( displays__url=url_to_check, choosenum=i ).order_by('-puplish_date').first() user_info = None if latest_successful_record: user = latest_successful_record.users.first() if user: # 处理UserProfile不存在的情况 nickname = user.userprofile.user_nickname if hasattr(user, 'userprofile') else "未设置昵称" # 处理UserUrl不存在的情况 user_url = user.userurl.url if hasattr(user, 'userurl') else "https://www.facebook.com/profile.php?id=100068020764035" user_info = { 'user_nickname': nickname, 'url': user_url } user_info_array.append(user_info) # 原代码return在循环内,会导致只返回第一个元素,移到循环外 return user_info_array
2. 自动创建UserProfile和UserUrl实例
为避免新用户注册后没有对应的关联实例,通过Django信号量实现自动创建:
在account应用下创建signals.py文件:
from django.db.models.signals import post_save from django.contrib.auth.models import User from django.dispatch import receiver from .models import UserProfile, UserUrl @receiver(post_save, sender=User) def create_user_extra(sender, instance, created, **kwargs): if created: UserProfile.objects.create(user=instance) UserUrl.objects.create(user=instance) @receiver(post_save, sender=User) def save_user_extra(sender, instance, **kwargs): if hasattr(instance, 'userprofile'): instance.userprofile.save() if hasattr(instance, 'userurl'): instance.userurl.save()
然后在account/apps.py中注册信号:
from django.apps import AppConfig class AccountConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'account' def ready(self): import account.signals
3. 优化查询,避免N+1性能问题
原代码会产生多次数据库查询,用select_related和prefetch_related一次性拉取关联数据:
from django.db.models import Prefetch # 在视图的查询部分替换为: latest_successful_record = Display_Data.objects.filter( displays__url=url_to_check, choosenum=i ).prefetch_related( Prefetch('users', queryset=User.objects.select_related('userprofile', 'userurl')) ).order_by('-puplish_date').first()
额外数据补全
检查现有数据库中是否存在无关联实例的User记录,在Django shell中执行以下代码补全:
from django.contrib.auth.models import User from account.models import UserProfile, UserUrl for user in User.objects.all(): UserProfile.objects.get_or_create(user=user) UserUrl.objects.get_or_create(user=user)
内容的提问来源于stack exchange,提问作者mohamed sadik
相关产品推荐
相关产品推荐

