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

Django条件post_save信号失效:创建超级用户不生成用户档案

解决创建超级用户时不生成用户档案的问题

你的代码存在几处关键问题导致逻辑失效,以下是具体修正方案:

1. 信号接收器位置错误

你把create_user_profile信号函数定义在了UserProfile类内部,Django无法正确识别并注册这个接收器,必须将其移到类外部。同时,post_save.connect调用也不应放在函数内部,否则会重复连接信号。

2. 重复定义save方法

你连续重写了两次save方法,后一个会完全覆盖前一个的逻辑,导致第一个图片处理代码完全失效,需要合并两个方法的功能。

修正后的完整代码

from django.db import models
from tinymce import models as tinymce_models
from accounts.models import CustomUser
from phone_field import PhoneField
from constrainedfilefield.fields import ConstrainedFileField
import os
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
import sys
from PIL import Image
from django.db.models.signals import post_save
import PIL

class UserProfile(models.Model):
    user = models.OneToOneField(CustomUser, null=True, on_delete=models.CASCADE)
    preferred_name = models.CharField(null=True, blank=True, max_length=75)
    pronouns = models.CharField(null=True, blank=True, max_length=40)
    phone = PhoneField(blank=True, help_text='Contact phone number')
    job_title = models.CharField(null=True, blank=True, max_length=75)
    birthdate = models.DateField(null=True, blank=True)
    bio = tinymce_models.HTMLField(null=True, blank=True)
    profile_image = ConstrainedFileField(
        null=True,
        blank=True,
        upload_to='projects/employee_profiles',
        content_types=['image/png', 'image/jpg', 'image/jpeg', 'image/gif'],
        max_upload_size=2097152,
    )

    def save(self, *args, **kwargs):
        if self.profile_image:
            # 先保存一次获取文件路径
            super().save(*args, **kwargs)
            img = Image.open(self.profile_image.path)
            
            # 裁剪为正方形
            if img.height > img.width:
                left = 0
                right = img.width
                top = (img.height - img.width) / 2
                bottom = (img.height + img.width) / 2
                img = img.crop((left, top, right, bottom))
            elif img.width > img.height:
                left = (img.width - img.height) / 2
                right = (img.width + img.height) / 2
                top = 0
                bottom = img.height
                img = img.crop((left, top, right, bottom))
            
            # 缩放到60x60分辨率
            if img.height > 60 or img.width > 60:
                output_size = (60, 60)
                img.thumbnail(output_size)
                img.save(self.profile_image.path)
            
            # 处理图片格式转换与宽度压缩
            image = Image.open(self.profile_image.path)
            outputIoStream = BytesIO()
            basewidth = 100
            wpercent = basewidth / image.size[0]
            hsize = int(image.size[1] * wpercent)
            imageTemproaryResized = image.resize((basewidth, hsize))
            imageTemproaryResized.save(outputIoStream, format='PNG')
            outputIoStream.seek(0)
            self.profile_image = InMemoryUploadedFile(outputIoStream, 'ConstrainedFileField',
                                                  "%s.png" % self.profile_image.name.split('.')[0], 'image/png',
                                                  sys.getsizeof(outputIoStream), None)
        
        # 统一保存所有修改
        super(UserProfile, self).save(*args, **kwargs)

    def __str__(self):
        return str(self.user)

# 信号接收器移至类外部
def create_user_profile(sender, instance, created, **kwargs):
    if created and not instance.is_superuser:
        UserProfile.objects.create(user=instance)

# 连接post_save信号
post_save.connect(create_user_profile, sender=CustomUser)

关键修正点说明

  • 信号接收器独立于类定义,确保Django能在应用加载时正确注册。
  • 合并后的save方法按顺序处理图片裁剪、缩放、格式转换,避免重复调用save引发的循环问题。
  • created and not instance.is_superuser的判断逻辑会严格筛选:仅当创建普通用户时生成档案,超级用户创建时直接跳过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:30:45