Django REST Framework中为何仅title提示必填,其他必填字段无提示?
问题:创建博客Post时仅title字段触发必填提示,其他必填字段无反馈
模型定义
class Post(models.Model): STATUS_CHOICES = [ ('P', _('Published')), ('D', _('Draft')), ('R', _('reject')) ] title = models.CharField(verbose_name=_("title"), max_length=255) slug = models.SlugField(null=True, unique=True, allow_unicode=True) lead = models.CharField(verbose_name=_("lead"), max_length=1024, blank=True, null=True) body = models.TextField(verbose_name=_("context")) thumbnail = models.ImageField(verbose_name=_("thumbnail"), upload_to='posts', blank=True, null=True) author = models.ForeignKey(UserAccount, verbose_name=_("author"), on_delete=models.CASCADE) status = models.CharField(_("status"), max_length=1, choices=STATUS_CHOICES, default=STATUS_CHOICES[1][0]) publish_time = models.DateTimeField(verbose_name=_("published at"), default=timezone.now) created_at = models.DateTimeField(verbose_name=_("created at"), auto_now_add=True) updated_at = models.DateTimeField(verbose_name=_("updated at"), auto_now=True) category = models.ManyToManyField(Category, verbose_name=_("Categorys"), related_name='Categorys') like_count = models.IntegerField(verbose_name=_("like"), default=0) dislike_count = models.IntegerField(verbose_name=_("dislike"), default=0) def save(self, *args, **kwargs): self.slug = slugify(self.title) super(Post, self).save(*args, **kwargs) class Meta: ordering = ['-publish_time'] def __str__(self): return self.title
序列化器定义
class PostListSerializer(ModelSerializer): dietale_url = HyperlinkedIdentityField( view_name='api:Post_detail' ) author = SerializerMethodField() class Meta: model = Post fields = [ 'title', 'author', 'lead', 'dietale_url', ] def get_author(self, obj): return obj.author.name
错误信息
创建Post时返回的错误:
{ "title": [ "This field is required." ] }
原因分析
Django REST Framework(DRF)的序列化器仅对**fields列表中包含的字段**执行验证逻辑:
title是模型必填字段且存在于序列化器的fields中,所以DRF会验证它的必填性,缺失时返回错误。body、author(模型外键)这些必填字段不在序列化器的fields列表里,序列化器会直接跳过对它们的验证,不会返回对应必填错误。但实际保存到数据库时,模型层面的约束会触发报错,只是序列化阶段未检测到。- 另外,
author字段使用SerializerMethodField,这是只读字段,无法接收创建时的输入数据,即使请求中传入author值也会被忽略。
解决方法
- 调整序列化器字段:如果该序列化器用于创建Post,需将所有模型必填字段(
title、body、author等)加入fields列表,同时将author改为可写字段类型,比如PrimaryKeyRelatedField:
class PostCreateSerializer(ModelSerializer): dietale_url = HyperlinkedIdentityField( view_name='api:Post_detail' ) class Meta: model = Post fields = [ 'title', 'body', 'author', 'lead', 'dietale_url', # 按需添加其他需要的字段 ]
- 拆分序列化器:通常列表展示用的序列化器和创建/更新用的序列化器分开设计,列表序列化器仅返回前端需要的展示字段,创建序列化器包含所有必填输入字段,职责更清晰。
内容的提问来源于stack exchange,提问作者mohammad baniasadi
相关产品推荐
相关产品推荐

