【问题标题】:Chaining update and get method in Django for updating fields在 Django 中链接更新和获取方法以更新字段
【发布时间】:2026-02-22 04:05:01
【问题描述】:

我有一个 Django 模型如下:

class IPGroup(models.Model):
    name = models.CharField(max_length=50, unique=True)
    junos_space_id = models.CharField(max_length=50)

class Jira(models.Model):
    jira_id = models.CharField(max_length=50, unique=True)
    ip_groups = models.ForeignKey(IPGroup, null=True, on_delete=models.SET_NULL)

现在我有一个原子 ORM 事务如下:

try:
    with transaction.atomic(): 
        IPGroup.objects.filter(id=2).update(junos_space_id=3)
        Jira.objects.filter(jira_id=2)).update(ip_groups_id=2)
except Exception:
    response = Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                        data={'status': 'Database error encountered'})

这在一切正常的情况下效果很好。但是,当发生错误时(例如 id 错误),filter 只会给出一个空的查询集,并且它永远不会遇到异常。

我尝试用 get 而不是 filter 重写它,如下所示:

try:
    with transaction.atomic(): 
        IPGroup.objects.get(id=2).update(junos_space_id=3)
        Jira.objects.get(jira_id=2)).update(ip_groups_id=2)
except Exception:
    response = Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                        data={'status': 'Database error encountered'})

但是是给我以下属性错误:

AttributeError: 'IPGroup' 对象没有属性 'update'

以干净的方式执行此操作的最佳方法是什么?

【问题讨论】:

  • filter() 返回一个查询集(可能为空),update() 仅适用于QuerySets。因此,将您的行拆分为 3:首先获取对象,然后更改其属性并保存。并且不要使用except Exception,而是使用except (IPGroup.DoesNotExist, Jira.DoesNotExist),因此您可以更具体地了解要捕获的异常类型。在这种情况下,我永远不会返回 500 错误,而是返回 404(找不到页面)错误或只是友好的用户错误。无论如何查询不存在的对象都不是数据库错误。
  • 顺便说一句,如果您假设硬编码 ids 在您拥有的每个安装中都相同(假设它们是常规的 Django 自动增量 id s)。也许你应该考虑某种辅助唯一标识符或 slug。

标签: python django django-queryset


【解决方案1】:

您需要将代码分解为 3 个步骤

  1. 首先get 然后下一个更新

     ip_group = IPGroup.objects.get(id=2)
    
  2. 更新字段

     ip_group.junos_space_id=3
    
  3. 保存

     ip_group.save()
    

供参考docs

【讨论】:

    【解决方案2】:

    很高兴,update() returns the number of rows matched by the query,所以如果你确实想使用.update() 而不是像@AJS 的回答所建议的那样加载、更新和保存对象,你可以这样做

    try:
        with transaction.atomic():
            if IPGroup.objects.filter(id=2).update(junos_space_id=3) == 0:
                raise ValueError("No IPGroups matched")
            if Jira.objects.filter(jira_id=2).update(ip_groups_id=2) == 0:
                raise ValueError("No Jiras matched")
    except Exception as exc:
        response = Response(
            status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            data={"status": "Database error encountered: %s" % exc},
        )
    

    【讨论】: