You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

注册用户关联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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:45:05