意外的Django ORM行为

问题描述 投票:0回答:1

我有一个函数,该函数必须根据其名称进行处理,但是对我来说很奇怪。

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个条目。

[请给我解释一下这种行为以及我应该如何操作。

python django
1个回答
0
投票

起初为了检查最好使用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)
© www.soinside.com 2019 - 2024. All rights reserved.