Django中post_save信号创建Profile时出现Profile不存在报错
问题描述
我通过post_save信号为每个新建的User自动创建Profile,Profile的followers多对多字段用来实现用户关注功能。但点击添加/取消关注按钮时,报错指向profile = Profile.objects.get(pk = pk)这一行,而且只有通过信号自动创建的Profile才会出现这个问题,推测问题出在Profile自动创建的逻辑里。
我的代码
signals.py
from django.db.models.signals import post_save from django.contrib.auth.models import User from .models import Profile from django.dispatch import receiver @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): if created: profile = Profile.objects.create(user = instance) profile.followers.add('1')
视图方法
class AddFollower(ListView): def post(self, request, pk , *args, **kwargs ): print('usuario aaaaaaaaaaaaaaaaaagregado') profile = Profile.objects.get(pk = pk) profile.followers.add(self.request.user) return redirect('profile', username = profile.user.username) class RemoveFollower(ListView): def post(self, request, pk , *args, **kwargs ): print(f'reeeeeeeeeeeeeeeeeeeeeeeemovingFollower2{request.user}') profile = Profile.objects.get(pk = pk) profile.followers.remove(self.request.user) return redirect('profile', username = profile.user.username)
Profile模型
class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) profile_img = models.ImageField(default='user.png') followers = models.ManyToManyField(User,blank=True, related_name='followers') def __str__(self): return f'{self.user.username} profile'
问题原因与解决办法
核心问题
信号代码里profile.followers.add('1')这行是错误的:followers是关联User的多对多字段,要求传入User实例或者整数类型的主键,但你传了字符串'1'。这种类型不匹配会导致Profile的多对多关系数据异常,后续操作时就会触发报错。
修复步骤
修正信号代码:
要么直接删掉错误的add('1')行,要么如果确实要给新用户添加初始关注,传入正确的参数类型(比如整数主键或者User实例):@receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): if created: profile = Profile.objects.create(user=instance) # 示例:添加id为1的用户作为初始关注(确保该用户存在) # try: # default_user = User.objects.get(pk=1) # profile.followers.add(default_user) # except User.DoesNotExist: # pass修复已有异常数据:
对于已经用错误代码创建的Profile,需要清理异常的关联数据。可以打开Django Shell执行以下命令:from your_app_name.models import Profile for profile in Profile.objects.all(): # 移除错误的字符串主键关联 invalid_entries = profile.followers.filter(pk__in=['1']) profile.followers.remove(*invalid_entries)优化视图(可选):
用get_object_or_404替代get,避免因为pk不存在直接抛出服务器错误,提升用户体验:from django.shortcuts import get_object_or_404 class AddFollower(ListView): def post(self, request, pk , *args, **kwargs ): profile = get_object_or_404(Profile, pk=pk) profile.followers.add(request.user) return redirect('profile', username=profile.user.username) class RemoveFollower(ListView): def post(self, request, pk , *args, **kwargs ): profile = get_object_or_404(Profile, pk=pk) profile.followers.remove(request.user) return redirect('profile', username=profile.user.username)
内容的提问来源于stack exchange,提问作者Rodolfo Schiavi
相关产品推荐
相关产品推荐

