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

Django post_save信号创建Perfil用户档案时first_name、last_name未入库

问题核心

Django信号触发数据库写入操作时,部分字段值未成功存储。

问题描述

在Django项目中使用信号机制,每当内置User模型新增用户注册记录时,自动在Perfil(用户档案)表创建关联的档案记录。目前username关联字段、email字段可正常获取并存储,但first_name、last_name字段始终无法成功赋值。

相关代码

Perfil模型定义

class Perfil(models.Model):
    username = models.OneToOneField(User, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=30, verbose_name="first name", blank=True)
    last_name = models.CharField(max_length=30, verbose_name="last name", blank=True)
    email = models.EmailField(max_length=75, verbose_name="email address", blank=True)

    def __str__(self):
        return self.username.username

new_profile信号实现

def new_profile(sender, instance, created, **kwargs):
    user_db = User.objects.filter(username__exact=instance).values().first()
    if created:
        Perfil.objects.create(
            username = instance
        )
        Perfil.objects.filter(username__exact=instance).update(
            first_name = user_db['first_name'],
            last_name = user_db['last_name'],
            email = user_db['email']
        )
post_save.connect(new_profile, sender=User)

问题补充说明

  • 最初尝试在create操作时直接传入所有字段赋值但未生效,改用先创建记录、再执行update更新字段的方案后问题仍未解决。
  • 数据库表查询结果显示:email字段正常存储,但last_name、first_name字段为空,问题表现如下:
    问题表现截图

问题原因与修复方案

根因分析

  1. 冗余查询逻辑问题:信号回调里传入的instance就是当前触发保存的User模型实例,完全不需要额外调用User.objects.filter再查一次数据库,多此一举还容易引入匹配错误。
  2. 字段值本身为空:post_save信号在User实例第一次写入数据库时触发,绝大多数默认注册流程(比如Django自带的UserCreationForm)首次创建用户时,只会提交username、密码、email字段,first_name、last_name本身就没有赋值,数据库里存的就是空字符串,不管你用create还是update,写进Perfil的自然是空值。
  3. 缺少后续同步逻辑:就算首次创建时姓名字段为空,后续用户补填个人信息再次保存User时,现有信号逻辑只判断if created,不会触发Perfil表的字段更新,自然一直是空。

修复代码

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User

@receiver(post_save, sender=User)
def sync_user_perfil(sender, instance, created, **kwargs):
    if created:
        # 新建用户时直接从当前实例取字段创建Perfil,无需二次查询、二次更新
        Perfil.objects.create(
            username=instance,
            first_name=instance.first_name,
            last_name=instance.last_name,
            email=instance.email
        )
    else:
        # 用户后续更新个人信息时,同步更新Perfil对应字段
        Perfil.objects.filter(username=instance).update(
            first_name=instance.first_name,
            last_name=instance.last_name,
            email=instance.email
        )

额外排查点

如果替换上述代码后first_name、last_name依旧为空,直接检查你的注册表单/视图逻辑:确认创建User实例的流程中,是否真的接收并给instance.first_name、instance.last_name赋了值。默认的UserCreationForm没有这两个字段的输入项,如果没自定义表单加字段,创建用户时这两个字段本来就是空值,信号逻辑再正确也拿不到内容。


内容的提问来源于stack exchange,提问作者Gustavo Megazorde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 10:15:37