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

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()

错误原因与解决方法

错误根源

  1. QuerySet赋值错误:信号中open_proposal_count是filter()返回的QuerySet对象,而number_of_proposals是数值类型字段(如IntegerField),直接将QuerySet赋值给数值字段会生成错误的SQL语句,触发MySQL的1241错误。
  2. 状态值不匹配:信号中判断状态用了"rejected",但模型status_choices定义的是"declined",导致该分支永远不会执行。

修复步骤

  1. 修正计数逻辑:将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
  1. 修正状态判断字符串:把"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")
  1. 可选性能优化:用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:30:51