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

Django & SQLite3客户注册问题:CustomerProfile数据未保存

问题:Django客户注册时CustomerProfile表无法保存数据,User表正常

开发Django项目时,客户注册功能出现异常——用户信息能正常保存到User表,但CustomerProfile表没有生成对应记录。项目包含app和user两个目录,相关代码如下:

app目录下的forms代码

from django import forms
from django.contrib.auth.forms import UserCreationForm
from user.models import Customer, CustomerProfile, generate_customer_id


class Customer_Register_Form(UserCreationForm):
    cus_name = forms.CharField(
        label="Customer Name", widget=forms.TextInput(attrs={"class": "form-control"})
    )
    email = forms.EmailField(widget=forms.EmailInput(attrs={"class": "form-control"}))
    phone_number = forms.CharField(
        widget=forms.TextInput(attrs={"class": "form-control"})
    )
    address = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control"}))

    username = forms.CharField(
        widget=forms.TextInput(
            attrs={"class": "form-control", "placeholder": "Enter your username"}
        )
    )
    password1 = forms.CharField(
        label="Password",
        widget=forms.PasswordInput(
            attrs={"class": "form-control", "placeholder": "Enter your password"}
        ),
    )
    password2 = forms.CharField(
        label="Confirm Password",
        widget=forms.PasswordInput(
            attrs={"class": "form-control", "placeholder": "Confirm your password"}
        ),
    )

    class Meta:
        model = Customer  # Use your custom user model
        fields = [
            "username",
            "cus_name",
            "password1",
            "password2",
            "email",
            "phone_number",
            "address",
        ]

    def save(self, commit=True):
        user = super().save(commit=False)
        user.cus_name = self.cleaned_data['cus_name']
        user.email = self.cleaned_data['email']
        user.phone_num = self.cleaned_data['phone_number']
        user.address = self.cleaned_data['address']
        
        if commit:
            user.save()
            # Assuming there's a one-to-one relationship between User and CustomerProfile
            CustomerProfile.objects.create(username=user, cus_id=generate_customer_id(user))

        return user

user目录下的models代码

from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db.models.signals import post_save
from phonenumber_field.modelfields import PhoneNumberField
from django.dispatch import receiver

# Create your models here.


class User(AbstractUser):
    class Role(models.TextChoices):
        CUSTOMER = "CUSTOMER", "Customer"
        PHARMACIST = "PHARMACIST", "Pharmacist"
        RETAILASSISTANT = "RETAILASSISTANT", "Retail Assistant"
        MANAGER = "MANAGER", "Manager"

    base_role = Role.CUSTOMER

    role = models.CharField(max_length=50, choices=Role.choices)

    def save(self, *args, **kwargs):
        if not self.pk:
            self.role = self.base_role
            return super().save(*args, **kwargs)


def generate_customer_id(instance):
    return f"CUS{instance.id:04d}"


def generate_pharmacist_id(instance):
    return f"PM{instance.id:04d}"


def generate_retail_assistant_id(instance):
    return f"RA{instance.id:04d}"


def generate_manager_id(instance):
    return f"M{instance.id:04d}"


class CustomerManager(BaseUserManager):
    def get_queryset(self, *args, **kwargs):
        result = super().get_queryset(*args, **kwargs)
        return result.filter(role=User.Role.CUSTOMER)


class Customer(User):
    base_role = User.Role.CUSTOMER

    customer = CustomerManager()

    class Meta:
        proxy = True

    def welcome(self):
        return "Only for customers"


class CustomerProfile(models.Model):
    username = models.OneToOneField(User, on_delete=models.CASCADE)
    password = models.CharField(max_length=16)
    cus_id = models.CharField(max_length=7, unique=True)
    cus_name = models.CharField(max_length=50)
    email = models.EmailField(max_length=50)
    phone_num = PhoneNumberField(blank=True, null=True)
    address = models.CharField(max_length=255, blank=True, null=True)


@receiver(post_save, sender=Customer)
def create_user_profile(sender, instance, created, **kwargs):
    if created and instance.role == "CUSTOMER":
        CustomerProfile.objects.create(
            username=instance, cus_id=generate_customer_id(instance)
        )


class PharmacistManager(BaseUserManager):
    def get_queryset(self, *args, **kwargs):
        result = super().get_queryset(*args, **kwargs)
        return result.filter(role=User.Role.PHARMACIST)


class Pharmacist(User):
    base_role = User.Role.PHARMACIST

    pharmacist = PharmacistManager()

    class Meta:
        proxy = True

    def welcome(self):
        return "Only for pharmacists"


class PharmacistProfile(models.Model):
    username = models.OneToOneField(User, on_delete=models.CASCADE)
    password = models.CharField(max_length=16)
    pharmacist_id = models.CharField(max_length=6, unique=True)


@receiver(post_save, sender=Pharmacist)
def create_pharmacist_profile(sender, instance, created, **kwargs):
    if created and instance.role == "PHARMACIST":
        PharmacistProfile.objects.create(
            username=instance, pharmacist_id=f"PM{instance.id:04d}"
        )


class RetailAssistantManager(BaseUserManager):
    def get_queryset(self, *args, **kwargs):
        result = super().get_queryset(*args, **kwargs)
        return result.filter(role=User.Role.RETAILASSISTANT)


class RetailAssistant(User):
    base_role = User.Role.RETAILASSISTANT

    RetailAssistant = RetailAssistantManager()

    class Meta:
        proxy = True

    def welcome(self):
        return "Only for retail assistants"


class RetailAssistantProfile(models.Model):
    username = models.OneToOneField(User, on_delete=models.CASCADE)
    password = models.CharField(max_length=16)
    retailassistant_id = models.CharField(max_length=6, unique=True)


@receiver(post_save, sender=RetailAssistant)
def create_retail_assistant_profile(sender, instance, created, **kwargs):
    if created and instance.role == "RETAILASSISTANT":
        RetailAssistantProfile.objects.create(
            username=instance, retailassistant_id=f"RA{instance.id:04d}"
        )


class ManagerManager(BaseUserManager):
    def get_queryset(self, *args, **kwargs):
        result = super().get_queryset(*args, **kwargs)
        return result.filter(role=User.Role.MANAGER)


class Manager(User):
    base_role = User.Role.MANAGER

    manager = ManagerManager()

    class Meta:
        proxy = True

    def welcome(self):
        return "Only for managers"


class ManagerProfile(models.Model):
    username = models.OneToOneField(User, on_delete=models.CASCADE)
    password = models.CharField(max_length=16)
    manager_id = models.CharField(max_length=5, unique=True)


@receiver(post_save, sender=Manager)
def create_manager_profile(sender, instance, created, **kwargs):
    if created and instance.role == "MANAGER":
        ManagerProfile.objects.create(
            username=instance, manager_id=f"M{instance.id:04d}"
        )

排查思路

  • 检查信号触发状态:在create_user_profile信号处理函数中添加打印或日志,验证当Customer实例创建时,该函数是否被执行
  • 核对CustomerProfile必填字段:查看模型中哪些字段未设置blank=True或null=True,确认创建Profile时是否提供了所有必填值
  • 验证表单save方法的Profile创建逻辑:手动在Django shell中执行表单save里的CustomerProfile.objects.create语句,检查是否抛出异常,比如字段不匹配、cus_id重复等问题
  • 排查代理模型的信号兼容性:因为Customer是User的代理模型,确认Django的post_save信号是否会正确发送给代理模型的sender,是否需要调整信号绑定的sender
  • 查看数据库与运行日志:检查Django运行日志中的报错信息,同时查看数据库是否存在约束冲突、事务未提交等情况
  • 验证generate_customer_id函数输出:确认该函数生成的cus_id是否符合字段长度要求,是否会出现重复值导致创建失败

内容的提问来源于stack exchange,提问作者FL C.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:06:01