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

Django中如何结合@setter与Auth Token正确设置Post的userkey?

问题解决:NOT NULL约束失败与用户关联问题

错误原因

你的@user.setter实现完全不符合要求:它没有接收要设置的用户对象参数,反而返回了一个ForeignKey字段定义,导致调用serializer.save(user=self.request.user)时,根本没有将用户赋值到userkey字段,数据库因userkey_id不为空的约束抛出错误。

两种修正方案

方案一:直接操作关联字段(最简方式)

不需要保留错误的@user.setter,直接在视图中使用模型实际的关联字段userkey:

  1. 修改Post模型:移除错误的@user.setter,保留只读的user属性用于返回用户名
from django.db import models
from accounts.models import CustomUser

class Post(models.Model):
    # 外键关联
    userkey = models.ForeignKey(CustomUser, on_delete=models.CASCADE) 

    # 其他字段
    title = models.CharField(max_length=100,blank=True)
    image= models.FileField(upload_to='files/', null=True, verbose_name="",blank=True)
    price = models.IntegerField(default=0,blank=True)
    description = models.TextField(blank=True)
    likes = models.IntegerField(default=0)
    tags = models.CharField(max_length=30,blank=True,default="tag1,tag2,...")
    date_modified = models.DateTimeField(auto_now=True,blank=True)
    created = models.DateTimeField(auto_now_add=True,blank=True)
    sold = models.BooleanField(default=False,blank=True)

    @property
    def user(self):
        return self.userkey.username

    @property
    def datejoined(self):
        return self.userkey.date_joined

    def __str__(self):
        return self.title
  1. 修改CreatePost视图:将serializer.save(user=self.request.user)改为传入userkey
class CreatePost(generics.CreateAPIView):
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]

    def perform_create(self,serializer):
        serializer.save(userkey = self.request.user)

方案二:正确实现@user.setter(保留user属性赋值)

如果你希望通过user属性来设置关联用户,需要正确实现setter方法,让它接收用户对象并赋值给userkey:

  1. 修改Post模型的setter:
from django.db import models
from accounts.models import CustomUser

class Post(models.Model):
    userkey = models.ForeignKey(CustomUser, on_delete=models.CASCADE) 

    # 其他字段(同上)

    @property
    def user(self):
        return self.userkey.username

    @user.setter
    def user(self, user_obj):
        # 接收用户对象,赋值给userkey
        self.userkey = user_obj

    @property
    def datejoined(self):
        return self.userkey.date_joined

    def __str__(self):
        return self.title
  1. 视图代码保持不变:
class CreatePost(generics.CreateAPIView):
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]

    def perform_create(self,serializer):
        serializer.save(user = self.request.user)

额外注意:序列化器配置

确保你的PostSerializer中,要么不包含user字段(因为它是模型的属性而非数据库字段),要么将其设置为只读字段:

from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
    user = serializers.ReadOnlyField()  # 仅用于返回用户名,不接收输入
    datejoined = serializers.ReadOnlyField()

    class Meta:
        model = Post
        fields = ['id', 'user', 'datejoined', 'title', 'image', 'price', 'description', 'likes', 'tags', 'date_modified', 'created', 'sold']
        # 或者排除userkey,避免暴露给前端
        # exclude = ['userkey']

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:55:28