注册用户关联Customer模型失败:User has no customer错误排查
问题:新注册User未自动关联Customer,跳转首页报错
注册用户成功后,后端未自动创建对应的Customer实例,跳转首页时触发以下错误:
Exception Value:
User has no customer.
该错误来自以下工具函数:
def cartData(request): if request.user.is_authenticated: customer = request.user.customer order, created = Order.objects.get_or_create(customer=customer, order_status='P') items = order.orderitem_set.all() cartItems = order.get_cart_items else: cookieData = cookieCart(request) cartItems = cookieData['cartItems'] order = cookieData['order'] items = cookieData['items'] return {'cartItems': cartItems, 'order': order, 'items': items}
Customer模型定义
class Customer(models.Model): user = models.OneToOneField( User, on_delete=models.CASCADE, null=True) first_name = models.CharField(max_length=255) last_name = models.CharField(max_length=255) email = models.EmailField(unique=True) phone = models.CharField(max_length=255) birth_date = models.DateField(null=True)
用户注册与登录视图
def UserRegister(request): if request.method == "POST": form = UserRegisterForm(request.POST) if form.is_valid(): form.save() username = form.cleaned_data['username'] password = form.cleaned_data['password1'] user = authenticate(username=username, password=password) login(request, user) messages.success(request, ("Registration successful, you are now logged in...")) return redirect('home') else: form = UserRegisterForm() return render(request, 'authenticate/register.html', {'form': form}) def UserLogin(request): if request.method == "POST": username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) messages.success(request, ("You were successfully logged in...")) return redirect('home') else: messages.success(request, ("There was an error logging in, please try again...")) return redirect('login') return render(request, 'authenticate/login.html', {})
解决方案
1. 注册时同步创建Customer实例
首先修改注册表单,添加Customer所需的必填字段:
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from django import forms class UserRegisterForm(UserCreationForm): first_name = forms.CharField(max_length=255, required=True) last_name = forms.CharField(max_length=255, required=True) email = forms.EmailField(required=True) phone = forms.CharField(max_length=255, required=True) birth_date = forms.DateField(required=False) class Meta: model = User fields = ['username', 'first_name', 'last_name', 'email', 'phone', 'birth_date', 'password1', 'password2']
然后修改注册视图,在用户保存后立即创建对应的Customer:
def UserRegister(request): if request.method == "POST": form = UserRegisterForm(request.POST) if form.is_valid(): # 保存用户 user = form.save() # 创建关联的Customer Customer.objects.create( user=user, first_name=form.cleaned_data['first_name'], last_name=form.cleaned_data['last_name'], email=form.cleaned_data['email'], phone=form.cleaned_data['phone'], birth_date=form.cleaned_data.get('birth_date') ) # 登录用户 username = form.cleaned_data['username'] password = form.cleaned_data['password1'] user = authenticate(username=username, password=password) login(request, user) messages.success(request, "注册成功,已自动登录...") return redirect('home') else: form = UserRegisterForm() return render(request, 'authenticate/register.html', {'form': form})
2. 用信号自动关联(需处理必填字段)
如果希望在User创建时自动触发Customer创建,可使用Django的post_save信号。注意需修改Customer模型允许phone字段为空:
# 修改Customer模型的phone字段 phone = models.CharField(max_length=255, blank=True)
然后在models.py中添加信号:
from django.db.models.signals import post_save from django.contrib.auth.models import User from django.dispatch import receiver from .models import Customer @receiver(post_save, sender=User) def create_customer(sender, instance, created, **kwargs): if created: # 利用User自带字段填充Customer Customer.objects.create( user=instance, first_name=instance.first_name, last_name=instance.last_name, email=instance.email, phone='', birth_date=None ) @receiver(post_save, sender=User) def save_customer(sender, instance, **kwargs): instance.customer.save()
3. 优化cartData函数避免直接报错
为兼容已有未关联Customer的用户,修改cartData函数使用get_or_create:
def cartData(request): if request.user.is_authenticated: # 自动创建缺失的Customer实例 customer, created = Customer.objects.get_or_create( user=request.user, defaults={ 'first_name': request.user.first_name, 'last_name': request.user.last_name, 'email': request.user.email, 'phone': '' } ) order, created = Order.objects.get_or_create(customer=customer, order_status='P') items = order.orderitem_set.all() cartItems = order.get_cart_items else: cookieData = cookieCart(request) cartItems = cookieData['cartItems'] order = cookieData['order'] items = cookieData['items'] return {'cartItems': cartItems, 'order': order, 'items': items}
内容的提问来源于stack exchange,提问作者David Henson
相关产品推荐
相关产品推荐

