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] 中,您基本上有两个部分:
- 进行过滤的命名参数,只有当它们能找到匹配所有过滤器的记录时,才会更新该记录;和
defaults=…
参数,这是一个值字典,将用于 更新 或 创建 该记录。
如果您因此只想更新 card_count
和 last_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
完全匹配,它将 仅 更新记录,因此如果defaults
和 kwargs
都包含相同的值,如果存在包含所有值的记录,您基本上什么都不做,或者如果不存在这样的记录,则创建一个新记录。
我在 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] 中,您基本上有两个部分:
- 进行过滤的命名参数,只有当它们能找到匹配所有过滤器的记录时,才会更新该记录;和
defaults=…
参数,这是一个值字典,将用于 更新 或 创建 该记录。
如果您因此只想更新 card_count
和 last_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
完全匹配,它将 仅 更新记录,因此如果defaults
和 kwargs
都包含相同的值,如果存在包含所有值的记录,您基本上什么都不做,或者如果不存在这样的记录,则创建一个新记录。