Django自定义注册用户时Profile未自动创建问题求助
问题描述
使用自定义注册表单创建User时,期望自动生成对应的Profile,但目前仅管理员后台手动创建Profile有效,自定义注册场景下Profile不会自动生成。访问/auth/profile/路径时触发错误:
RelatedObjectDoesNotExist at /auth/profile/ User has no profile. (user is creating but profile is not)
同时,apps.py中的import authenticate_me.signals语句显示灰色,IDE提示“未被使用”。
提供的代码
Models.py
from distutils.command.upload import upload from email.policy import default from django.db import models from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import User from PIL import Image # Create your models here. class User(AbstractUser): is_user = models.BooleanField(default=False) is_doctor = models.BooleanField( default=False) first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) class User_reg(models.Model): user = models.OneToOneField('User',on_delete=models.CASCADE, primary_key=True) fname = models.CharField(max_length=50,blank=False) lname = models.CharField(max_length=50,blank=False) email = models.EmailField(max_length=100,blank=False) address = models.TextField(max_length=500,blank=False) gender = models.CharField(max_length=7, blank=False) phone = models.CharField(max_length=12,unique=True,blank=False) Username = models.CharField(max_length=100,blank=False,unique=True) Userpassword = models.CharField(max_length=100,blank=False) def __str__(self): return self.fname class dr_reg(models.Model): user = models.OneToOneField('User',on_delete=models.CASCADE, primary_key=True) fname = models.CharField(max_length=50,blank=False) lname = models.CharField(max_length=50,blank=False) image = models.ImageField(upload_to="image") specialisation = models.CharField(max_length=100,blank=False) qualificaton = models.CharField(max_length=100,blank=False) phone = models.CharField(max_length=12,blank=False,unique=True) gender = models.CharField(max_length=7,blank=False) address = models.TextField(max_length=500,blank=False) state = models.CharField(max_length=50,blank=False) city = models.CharField(max_length=50,blank=False) zip = models.CharField(max_length=50,blank=False) email = models.EmailField(max_length=50,blank=False) dUsername = models.CharField(max_length=100,blank=False,unique=True) dPassword = models.CharField(max_length=100,blank=False) def __str__(self): return self.fname class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) avatar = models.ImageField(default='#', upload_to='profile_images') bio = models.TextField() def __str__(self): return self.bio def save(self, *args, **kwargs): super().save() img = Image.open(self.avatar.path) if img.height > 100 or img.width > 100: new_img = (100, 100) img.thumbnail(new_img) img.save(self.avatar.path)
views.py
def dr_register(request): if request.method == "POST": fname = request.POST.get('dfname') lname = request.POST.get('dlname') image = request.POST.get('img') qualification = request.POST.get('qualification') specialist = request.POST.get('specialisation') phone = request.POST.get('dphone') gender = request.POST.get('dsex') address = request.POST.get('dadd') state = request.POST.get('state') city = request.POST.get('city') zip = request.POST.get('zip') email = request.POST.get('demail') dr_username = request.POST.get('duname') dr_password = request.POST.get('dpass') mydoctor = User.objects.create_user(dr_username, email, dr_password) mydoctor.first_name = fname mydoctor.last_name = lname mydoctor.is_doctor = True mydoctor.save() dr_reg.objects.create(fname=fname,lname=lname,image=image, qualificaton=qualification, specialisation = specialist, phone= phone, gender=gender, address=address, state=state, city=city, zip=zip, email=email, dUsername=dr_username, dPassword= dr_password,user=mydoctor) # dr_register.save() messages.success(request, 'Registeration successful') return render(request, 'user/login.html') else: return render(request, 'doctor/register.html') @login_required def profile(request): if request.method == 'POST': user_form = UpdateUserForm(request.POST, instance=request.user) profile_form = UpdateProfileForm(request.POST, request.FILES, instance=request.user.profile) if user_form.is_valid() and profile_form.is_valid(): user_form.save() profile_form.save() messages.success(request, 'Your profile is updated successfully') return redirect(to='users-profile') else: user_form = UpdateUserForm(instance=request.user) profile_form = UpdateProfileForm(instance=request.user.profile) context = { 'user_form': user_form, 'profile_form': profile_form } return render(request, 'user/edit-profile.html', context)
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 Profile @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): if created: Profile.objects.create(user=instance).save() @receiver(post_save, sender=User) def save_profile(sender, instance, **kwargs): instance.profile.save()
apps.py
from django.apps import AppConfig class LoginModuleConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'authenticate_me' def ready(self): import authenticate_me.signals
问题原因及修复步骤
1. 信号监听了错误的User模型
问题:signals.py中导入的是Django默认的django.contrib.auth.models.User,但项目使用的是自定义的User(AbstractUser),导致信号仅监听默认User的创建事件,自定义User创建时不会触发Profile生成逻辑。
修复:修改signals.py中的User导入,替换为项目自定义的User模型:
from django.db.models.signals import post_save # 替换默认User导入为自定义User from .models import User from django.dispatch import receiver from .models import Profile @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): if created: # create()方法已自动保存,无需额外调用save() Profile.objects.create(user=instance) @receiver(post_save, sender=User) def save_profile(sender, instance, **kwargs): instance.profile.save()
2. 未配置Django使用自定义User模型
问题:若settings.py中未设置AUTH_USER_MODEL,Django会继续使用默认User模型,信号和自定义User的关联逻辑会失效。
修复:在项目的settings.py中添加以下配置:
AUTH_USER_MODEL = 'authenticate_me.User'
3. 解决apps.py中导入未被使用的提示
问题:IDE提示import authenticate_me.signals未被使用,是因为导入语句仅用于加载信号,没有直接调用。
修复:可以添加注释告诉IDE忽略提示:
from django.apps import AppConfig class LoginModuleConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'authenticate_me' def ready(self): # noqa 告诉IDE忽略未使用的提示 import authenticate_me.signals # noqa
4. 补全已存在的无Profile的用户
问题:之前创建的User可能没有对应的Profile,需要批量补全。
修复:在Django Shell中执行以下命令:
from authenticate_me.models import User, Profile # 为所有无Profile的用户创建默认Profile for user in User.objects.filter(profile__isnull=True): Profile.objects.create(user=user, bio='', avatar='#')
验证修复效果
- 重启Django服务器
- 通过自定义注册表单创建新User
- 访问
/auth/profile/路径,确认不再出现RelatedObjectDoesNotExist错误
内容的提问来源于stack exchange,提问作者Ashraf Patel

