objects.update_or_create() 在数据库中创建一条新记录而不是更新现有记录

objects.update_or_create() creates a new record in database rathe than update exisiting record

我在 Django 中创建了一个模型,并从 API 中获取数据。我正在尝试使用 update_or_create 方法从 API 获取数据并将其存入我的数据库。但是,我可能对它的工作原理感到困惑。

当我第一次 运行 它按预期将数据添加到数据库中时,但是如果我要更新记录的一个字段 - 来自 API 的数据已更改相应记录 - 然后 运行 再次更改,它正在创建新记录而不是更新现有记录。

所以在下面的场景中,我 运行 它和记录 Commander Legends 的计数是 718,然后我在数据库中手动更新为 100 .当我再次 运行 时,它会创建一条新记录,计数为 718

根据我的理解,它应该更新记录而不是创建新记录。

views.py

def set_update(request):
    try:
        discover_api = requests.get('https://api.scryfall.com/sets').json()
        set_data = discover_api['data']
        while discover_api['has_more']:
            discover_api = requests.get(discover_api['next_page']).json()
            set_data.extend(discover_api['data'])
    except HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}')
    except Exception as err:
        print(f'Other error occurred: {err}')

    sorted_data = sorted(set_data, key=lambda k: k['releaseDate'], reverse=False)

    for i in sorted_data:
        Set.objects.update_or_create(
            scry_id=i.get('id'),
            code=i.get('code'),
            name=i.get('name'),
            type=i.get('set_type').replace("_", " ").title(),
            release_date=i.get('released_at'),
            card_count=i.get('card_count'),
            is_digital_only=i.get('digital', False),
            is_non_foil_only=i.get('nonfoil_only', False),
            is_foil_only=i.get('foil_only', False),
            block_name=i.get('block'),
            block_code=i.get('block_code'),
            parent_set_code=i.get('parent_set_code'),
            tcgplayer_id=i.get('tcgplayer_id'),
            last_modified=date.today(),

            defaults={
                'scry_id': i.get('id'),
                'code': i.get('code'),
                'name': i.get('name'),
                'type': i.get('set_type').replace("_", " ").title(),
                'release_date': i.get('released_at'),
                'card_count': i.get('card_count'),
                'is_digital_only': i.get('digital', False),
                'is_non_foil_only': i.get('nonfoil_only', False),
                'is_foil_only': i.get('foil_only', False),
                'block_name': i.get('block'),
                'block_code': i.get('block_code'),
                'parent_set_code': i.get('parent_set_code'),
                'tcgplayer_id': i.get('tcgplayer_id'),
                'last_modified': date.today(),
            }
        )
    return redirect('dashboard:sets')

截图

update_or_create(…) [Django-doc] 中,您基本上有两个部分:

  1. 进行过滤的命名参数,只有当它们能找到匹配所有过滤器的记录时,才会更新该记录;和
  2. defaults=… 参数,这是一个值字典,将用于 更新创建 该记录。

如果您因此只想更新 card_countlast_modified,它看起来像:

Set.objects.update_or_create(
    scry_id=i.get('id'),
    code=i.get('code'),
    name=i.get('name'),
    type=i.get('set_type').replace('_', ' ').title(),
    release_date=i.get('released_at'),
    is_digital_only=i.get('digital', False),
    is_non_foil_only=i.get('nonfoil_only', False),
    is_foil_only=i.get('foil_only', False),
    block_name=i.get('block'),
    block_code=i.get('block_code'),
    parent_set_code=i.get('parent_set_code'),
    tcgplayer_id=i.get('tcgplayer_id'),
    defaults={
        <b>'card_count': i.get('card_count')</b>,
        <b>'last_modified': date.today()</b>
    }
)

如果您因此在 kwargs 处添加 card_count,如果 card_count 完全匹配,它将 更新记录,因此如果defaultskwargs 都包含相同的值,如果存在包含所有值的记录,您基本上什么都不做,或者如果不存在这样的记录,则创建一个新记录。