我有一个函数,该函数必须根据其名称进行处理,但是对我来说很奇怪。
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
变量中有2个字符串。
在步骤1上,我一无所有,空的QuerySet。然后,在步骤2中,我创建了新的艺术家,同时在existing
var中有一些条目!因此,在第3步中,我具有true,扩展result
,并且已经有4个条目。
[请给我解释一下这种行为以及我应该如何操作。
起初为了检查最好使用exists()
。
existing = Artist.objects.filter(title__in=artists)
existing.exists() # return True or False
如果要说您的问题,我认为这可能与错误使用value_list
有关:
existing.values_list('title')
因为您将返回元组列表格式,如:
[('125231',), ('125246',), ('219',)]
因此,您在这里比较字符串列表和元组列表,这就是为什么它不删除现有字符串。
但是您期望这样:
['125231', '125246', '219',]
因此,为了具有字符串列表而不是元组列表,您需要添加flat=True
existing.values_list('title', flat=True)