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

Django注册API问题:Player模型height与handicap字段无法保存

问题诊断与修复方案

你的核心问题是Player模型的height和handicap字段无法保存,根源在于信号函数的反向关联错误、User创建逻辑的密码处理问题,以及信号与序列化器的执行顺序冲突。以下是具体修复步骤:


1. 修正models.py中的信号函数与字段默认值

首先解决信号函数中错误的反向关联属性:

from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
from django.contrib.auth.models import User
from django.dispatch import receiver
from django.db.models.signals import post_save
from datetime import datetime

class Player(models.Model):
    def __str__(self):
        return self.user.username

    # 可选:设置related_name,让User实例可以通过user.profile访问Player
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    handicap = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(28)])
    height = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(250)])
    # 修正默认值:去掉括号,确保每次注册都用当前时间
    registration_date = models.DateTimeField(default=datetime.now)

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Player.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    # 若设置了related_name='profile',用instance.profile.save();否则用instance.player.save()
    instance.profile.save()

2. 修复serializers.py中的创建逻辑

主要解决密码明文存储问题,以及优化Player字段的赋值流程:

from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueValidator
from django.contrib.auth.password_validation import validate_password
from django.core.validators import MaxValueValidator, MinValueValidator
from .models import Player

class RegisterSerializer(serializers.ModelSerializer):
    first_name = serializers.CharField(required=True)
    last_name = serializers.CharField(required=True)
    email = serializers.EmailField(required=True, validators=[UniqueValidator(queryset=User.objects.all())])
    password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
    password2 = serializers.CharField(write_only=True, required=True)
    height = serializers.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(250)])
    handicap = serializers.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(28)])

    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'email', 'password', 'password2', 'height', 'handicap')

    def validate(self, attrs):
        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError({'password': "密码不匹配!"})
        return attrs

    def create(self, validated_data):
        # 提取Player专属字段
        player_fields = {
            'height': validated_data.pop('height'),
            'handicap': validated_data.pop('handicap')
        }
        # 创建User实例,用set_password加密密码
        user = User.objects.create(
            username=validated_data['email'],
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name'],
            email=validated_data['email']
        )
        user.set_password(validated_data['password'])
        user.save()
        # 直接创建Player并赋值,避免信号创建后再修改
        Player.objects.create(user=user, **player_fields)
        return user

3. 可选:简化信号逻辑(避免重复操作)

如果已经在序列化器中处理Player的创建,可以移除create_user_profile信号,或者修改为get_or_create避免重复创建:

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Player.objects.get_or_create(user=instance)

验证修复

完成修改后重启服务,发送注册请求,检查数据库中Player表的height和handicap字段是否已正确保存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:05:17