python - 意外的 Django ORM 行为
问题描述
我有一个函数,它必须按照它的名字做东西,但它对我来说很奇怪。
def get_or_create_artists_by_metadata(metadata: Dict[str, str]) -> List[Optional[Artist]]:
if artists := metadata.get('artist'):
artists = parse_artists_from_string(artists) # returns list of strings
try:
existing = Artist.objects.filter(title__in=artists) # 1
except Exception as err:
log.exception('Database error!')
log.exception(err)
return []
new_artists_list = list(set(artists) - set(itertools.chain(*existing.values_list('title'))))
objs = [Artist(title=artist) for artist in new_artists_list]
try:
new_artists = Artist.objects.bulk_create(objs) # 2
except Exception as err:
log.exception('Error during artists creating!')
return [*existing]
result = [*existing]
if new_artists: # 3
result.extend(new_artists)
return result
else:
return []
例如,我在artists
var 中有 2 个字符串。
在第 1 步中,我一开始什么都没有,清空 QuerySet。然后在第 2 步中,我创建了新艺术家,同时我在existing
var 中有一些条目!所以在第 3 步我有 true, extend result
,并且已经有 4 个条目。
请解释一下这种行为以及我应该如何操作它。
解决方案
首先为了检查是否存在,最好使用exists()
.
existing = Artist.objects.filter(title__in=artists)
existing.exists() # return True or False
如果要说您的问题,我相信它可能与value_list
此处的错误使用有关:
existing.values_list('title')
因为您将返回元组列表的格式,例如:
[('125',), ('126',), ('219',)]
所以在这里你比较一个字符串列表和一个元组列表,这就是它不删除现有字符串的原因。
但你期望这样:
['125', '126', '219',]
因此,为了获得字符串列表而不是元组列表,您需要添加flat=True
existing.values_list('title', flat=True)
以及声明的结果:
new_artists_list = list(set(artists) - set(itertools.chain(*existing.values_list('title', flat=True))))
将仅返回未使用的 id 字符串。
推荐阅读
- python - 写入文本并保存对话框
- php - Laravel 7-从数据库中获取数据时出现未定义的偏移错误
- networking - 如何通过 WiFi 控制开关?
- python - 如何使用 GDB 调试异步协程?
- ssl - System.IO.Exception:由于意外的打包格式,握手失败
- javascript - 在 Prestashop 部分 (product.tpl) 中插入动态 Google 图表
- python - 带有Tkinter和openCV的图像编辑软件,以及如何制作一个达到功能并显示它的按钮
- python - Tkinter 登录表单
- assembly - 在 32 位机器中取反 64 位数字
- python - Pythong梯度下降线性回归计算不好