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

Django中QuerySet无client属性异常排查及解决方案咨询

问题:'QuerySet' object has no attribute 'client' 异常解决

异常描述

遇到异常:'QuerySet' object has no attribute 'client',其中client是Master模型中关联Client的外键(一对多关系),需求是无记录则创建,有记录则更新。

相关日志

2023-09-25 10:29:25,768 - facebookapi.fetchMetadata - CRITICAL - about to save to master
2023-09-25 10:29:25,771 - facebookapi.fetchMetadata - CRITICAL - Master exists now update...
2023-09-25 10:29:25,773 - facebookapi.fetchMetadata - CRITICAL - _master.save() Exception: 'QuerySet' object has no attribute 'client'

模型定义

class Client(models.Model):
    id = models.BigAutoField(primary_key=True),
    name = models.CharField(max_length=200, blank=False, null=True)
    # more fields abbreviated

class Master(models.Model):
    id = models.BigAutoField(primary_key = True)
    client = models.ForeignKey(Client, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    user_metadata = models.JSONField(max_length=5000, null=True, blank=True)
    user_id = models.CharField(max_length=500, blank=False, null = True)
    user_name = models.CharField(max_length=500, blank=False, null = True)
    # more fields abbreviated

报错代码

logger.critical("about to save to master+++++++++++++++++++++OOOOOOOOOOOO+++++++++++++")

try:
    _master = Master.objects.filter(client=client_fk) 
    if _master is None:
        logger.critical("Master does not exist now create...")
        new_master = Master.objects.create()
        new_master.client = client_fk
        new_master.user_id = user_id
        new_master.user_name = result["name"]
        new_master.user_apprequests = _connections1["apprequests"]
        new_master.user_business_users = _connections1["business_users"]
        new_master.user_businesses = _connections1["businesses"]
        new_master.user_accounts = _connections1["accounts"]
        new_master.user_adaccounts = _connections1["adaccounts"]
        new_master.user_assigned_ad_accounts = _connections1["assigned_ad_accounts"]
        new_master.user_assigned_pages = _connections1["assigned_pages"]
        new_master.user_permissions = _connections1["permissions"]
        new_master.user_personal_ad_accounts = _connections1["personal_ad_accounts"]
        new_master.user_metadata = result["metadata"]
        new_master.account_status = "created"

        new_master.save()
    else:
        logger.critical("Master exists now update...")
        logger.critical("Master.client: %s", _master.client)
        #_master.client = client_fk
        _master.user_id = user_id
        _master.user_name = result["name"]
        _master.user_apprequests = _connections1["apprequests"]
        _master.user_business_users = _connections1["business_users"]
        _master.user_businesses = _connections1["businesses"]
        _master.user_accounts = _connections1["accounts"]
        _master.user_adaccounts = _connections1["adaccounts"]
        _master.user_assigned_ad_accounts = _connections1["assigned_ad_accounts"]
        _master.user_assigned_pages = _connections1["assigned_pages"]
        _master.user_permissions = _connections1["permissions"]
        _master.user_personal_ad_accounts = _connections1["personal_ad_accounts"]
        _master.user_metadata = result["metadata"]
        new_master.account_status = "updated"

        _master.save()

    return Response("Master saved", status=status.HTTP_200_OK)
except Exception as e:
    logger.critical("_master.save() Exception: %s", e)
    return Response(e, status=status.HTTP_400_BAD_REQUEST)

已尝试方案

  • 将过滤条件改为client_id,修改模型将client改为client_id并迁移,报错找不到client_id_id
  • 移除外键再重新添加并迁移,无效

解决方案

核心问题分析

  1. filter()返回QuerySet而非单个对象:Master.objects.filter(client=client_fk)返回的是符合条件的所有记录集合(QuerySet),不是单个Master实例,所以直接访问_master.client会报错,且QuerySet没有save()方法。
  2. 判断条件错误:QuerySet永远不会等于None,即使没有匹配记录,它也是空的QuerySet,所以if _master is None永远为False,会直接进入更新分支。

修复步骤

不需要创建新模型、删除迁移或放弃外键,直接修改代码即可:

方法1:使用get()配合异常处理(适合唯一记录场景)

如果每个Client对应唯一的Master记录,用get()获取单个对象,捕获DoesNotExist异常来创建新记录:

from django.core.exceptions import ObjectDoesNotExist

logger.critical("about to save to master+++++++++++++++++++++OOOOOOOOOOOO+++++++++++++")

try:
    # 获取单个Master对象,不存在则抛出异常
    _master = Master.objects.get(client=client_fk)
    logger.critical("Master exists now update...")
    # 更新字段
    _master.user_id = user_id
    _master.user_name = result["name"]
    _master.user_apprequests = _connections1["apprequests"]
    _master.user_business_users = _connections1["business_users"]
    _master.user_businesses = _connections1["businesses"]
    _master.user_accounts = _connections1["accounts"]
    _master.user_adaccounts = _connections1["adaccounts"]
    _master.user_assigned_ad_accounts = _connections1["assigned_ad_accounts"]
    _master.user_assigned_pages = _connections1["assigned_pages"]
    _master.user_permissions = _connections1["permissions"]
    _master.user_personal_ad_accounts = _connections1["personal_ad_accounts"]
    _master.user_metadata = result["metadata"]
    _master.account_status = "updated"
    _master.save()
except ObjectDoesNotExist:
    logger.critical("Master does not exist now create...")
    # 创建新记录,一次性赋值更高效
    _master = Master.objects.create(
        client=client_fk,
        user_id=user_id,
        user_name=result["name"],
        user_apprequests=_connections1["apprequests"],
        user_business_users=_connections1["business_users"],
        user_businesses=_connections1["businesses"],
        user_accounts=_connections1["accounts"],
        user_adaccounts=_connections1["adaccounts"],
        user_assigned_ad_accounts=_connections1["assigned_ad_accounts"],
        user_assigned_pages=_connections1["assigned_pages"],
        user_permissions=_connections1["permissions"],
        user_personal_ad_accounts=_connections1["personal_ad_accounts"],
        user_metadata=result["metadata"],
        account_status="created"
    )
except Exception as e:
    logger.critical("_master.save() Exception: %s", e)
    return Response(str(e), status=status.HTTP_400_BAD_REQUEST)

return Response("Master saved", status=status.HTTP_200_OK)

方法2:使用update_or_create(Django内置简洁方案)

Django提供的update_or_create方法直接实现“无则创建,有则更新”逻辑:

logger.critical("about to save to master+++++++++++++++++++++OOOOOOOOOOOO+++++++++++++")

try:
    # 用client作为匹配条件,defaults为要更新的字段
    _master, created = Master.objects.update_or_create(
        client=client_fk,
        defaults={
            'user_id': user_id,
            'user_name': result["name"],
            'user_apprequests': _connections1["apprequests"],
            'user_business_users': _connections1["business_users"],
            'user_businesses': _connections1["businesses"],
            'user_accounts': _connections1["accounts"],
            'user_adaccounts': _connections1["adaccounts"],
            'user_assigned_ad_accounts': _connections1["assigned_ad_accounts"],
            'user_assigned_pages': _connections1["assigned_pages"],
            'user_permissions': _connections1["permissions"],
            'user_personal_ad_accounts': _connections1["personal_ad_accounts"],
            'user_metadata': result["metadata"],
            'account_status': "created"
        }
    )
    # 更新状态:如果是已存在的记录,将状态改为updated
    if not created:
        _master.account_status = "updated"
        _master.save()
except Exception as e:
    logger.critical("_master.save() Exception: %s", e)
    return Response(str(e), status=status.HTTP_400_BAD_REQUEST)

return Response("Master saved", status=status.HTTP_200_OK)

额外注意点

  • 模型Client的id字段末尾多了一个逗号,会导致字段变成元组引发异常,需删除:
    class Client(models.Model):
        id = models.BigAutoField(primary_key=True)  # 去掉末尾逗号
        name = models.CharField(max_length=200, blank=False, null=True)
        # more fields abbreviated
    
  • 确保client_fk是Client实例,若用主键值过滤,需写成Master.objects.filter(client_id=client_fk_id)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:05:23