Django结合MySQL保存模型时报错(1241, 'Operand should contain 1 column(s)')求助
Django保存Proposal模型时出现MySQL错误(1241, 'Operand should contain 1 column(s)')
在Django应用中使用MySQL数据库,保存Proposal模型时返回以下错误:
(1241, 'Operand should contain 1 column(s)')
该错误在两种场景下都会触发:
- 在Admin界面创建、编辑或保存模型时
- 通过Django Rest Framework视图保存或编辑时
相关代码
Model
class Proposal(models.Model): """ Model for Proposals """ status_choices = ( ("pending", _("Pending")), ("accepted", _("Accepted")), ("declined", _("Declined")), ) related_request = models.ForeignKey(Request, on_delete=models.CASCADE, verbose_name=_('Request'), help_text=_('Request')) user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, verbose_name=_('User'), help_text=_('User')) price = models.IntegerField(verbose_name=_('Price'), help_text=_('Price')) notes = models.TextField(verbose_name=_('Notes'), help_text=_('Notes'), null=True, blank=True) estimated_time = models.CharField(max_length=100, verbose_name=_('Estimated time'), help_text=_('Estimated time')) date_created = models.DateTimeField(verbose_name=_('Date created'), help_text=_('Date created'), auto_now_add=True) date_modified = models.DateTimeField(verbose_name=_('Date modified'), help_text=_('Date modified'), auto_now=True) status = models.CharField(max_length=100, verbose_name=_('Proposal status'), help_text=_('Proposal status'), choices=status_choices, default="pending") checked_by_admin = models.BooleanField(verbose_name=_("Checked by admins"), default=False, help_text=_("Check this only if you are an admin and toke actions with this request")) file = models.FileField(upload_to="proposals_files", help_text='File attached with the proposal', verbose_name='Attached file', null=True, ) client_notes = models.TextField(verbose_name=_('Client Notes'), help_text=_('Client Notes'), null=True, blank=True) def __str__(self): return self.related_request.type + ' ' + self.related_request.finishing_type class Meta: verbose_name = _('Proposal') verbose_name_plural = _('Proposals')
DRF View
@api_view(["POST"]) @permission_classes([IsAuthenticated]) def react_to_proposal(request): """ Api Function that applies the client reaction to proposals """ if request.method == "POST": proposal_id = request.data['proposal_id'] is_accept = request.data['is_accept'] notes = request.data['notes'] print(proposal_id) print(is_accept) print(notes) proposal_object = Proposal.objects.get(id=proposal_id) proposal_object.status = "accepted" if is_accept else "declined" proposal_object.client_notes = notes proposal_object.save()
post_save信号
@receiver(post_save, sender=Proposal) def proposal_post_save(sender, instance, created, **kwargs): """ Signal for post saving proposal """ if instance.checked_by_admin and instance.status == "pending": send_notification_to_one(instance.related_request.user.id, "A supplier has sent a proposal on your request") elif instance.checked_by_admin and instance.status == "accepted": send_notification_to_one(instance.user.id, f"Your proposal {instance.id} has been accepted, " f"Rolla technical team will contact team shortly " f"to close the deal") elif instance.checked_by_admin and instance.status == "rejected": send_notification_to_one(instance.user.id, f"Your proposal {instance.id} has been rejected") open_proposal_count = Proposal.objects.filter(status="pending", related_request=instance.related_request) instance.related_request.number_of_proposals = open_proposal_count instance.related_request.save()
错误原因与解决方法
错误根源
- QuerySet赋值错误:信号中
open_proposal_count是filter()返回的QuerySet对象,而number_of_proposals是数值类型字段(如IntegerField),直接将QuerySet赋值给数值字段会生成错误的SQL语句,触发MySQL的1241错误。 - 状态值不匹配:信号中判断状态用了
"rejected",但模型status_choices定义的是"declined",导致该分支永远不会执行。
修复步骤
- 修正计数逻辑:将QuerySet替换为
count()方法获取数量:
open_proposal_count = Proposal.objects.filter(status="pending", related_request=instance.related_request).count() instance.related_request.number_of_proposals = open_proposal_count
- 修正状态判断字符串:把
"rejected"改为模型中定义的"declined":
elif instance.checked_by_admin and instance.status == "declined": send_notification_to_one(instance.user.id, f"Your proposal {instance.id} has been rejected")
- 可选性能优化:用
update()直接更新关联请求,减少一次数据库查询:
# 替换原有的instance.related_request赋值与save()逻辑 Request.objects.filter(id=instance.related_request.id).update( number_of_proposals=Proposal.objects.filter(status="pending", related_request=instance.related_request).count() )
验证
修正后,Admin界面和DRF视图保存Proposal时均不会触发1241错误,同时通知逻辑能正确处理declined状态的情况。
内容的提问来源于stack exchange,提问作者Ahmed Wagdi
相关产品推荐
相关产品推荐

