python—如何将一个对象与具有多个manyField的多个对象大容量关联?

9lowa7mx  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(256)

我有一个模型是这样的:

class Keyword(models.Model):
    name = models.CharField(unique=True)

class Post(models.Model):
    title = models.CharField()
    keywords = models.ManyToManyField(
        Keyword, related_name="posts_that_have_this_keyword"
    )

现在我要迁移所有 Post 一个名字不正确的人的名字 Keyword 一个新的名字 Keyword . 还有多个名字不正确 Keyword s。
我可以执行以下操作,但它会导致许多sql查询。

for keyword in Keyword.objects.filter(is_wrongly_named=True).iterator():
    old = keyword
    new, _ = Keyword.objects.get_or_create(name='some proper name')
    for note in old.notes_that_have_this_keyword.all():
        note.keywords.add(old)
    old.delete()

有没有一种方法可以在最小化执行的sql查询的同时实现这一点?
我更喜欢django-orm解决方案而不是原始的sql解决方案,因为我没有深入研究sql就直接进入了django-orm,对sql不太熟悉。
谢谢您。

zhte4eai

zhte4eai1#

如果您想使用m2m关系执行批量操作,我建议您直接对连接两个对象的表执行操作。django允许您使用 through 对象的m2m属性。
因此,要获得连接关键字和post的表,您可以引用 Keyword.posts_that_have_this_keyword.through 或者 Post.keywords.through . 我建议你给这个变量分配一个好名字,比如:

KeywordPost = Post.keywords.through

一旦你得到了一个表上的大容量操作可以执行。
批量删除错误条目

KeywordPost.objects.filter(keyword__is_wrongly_named=True).delete()

批量创建新条目

invalid_keyword_posts = KeywordPost.objects.filter(keyword__is_wrongly_named=True)
post_ids_to_update = invalid_keyword_posts.values_list("post_id", flat=True)
new_keyword_posts = [KeywordPost(post_id=p_id, keyword=new_keyword) for p_id in post_ids_to_update]
KeywordPost.objects.bulk_create(new_keyword_posts)

基本上,您可以访问orm在此联接表上提供的所有特性。这样你应该可以获得更好的表现。
您可以在此处阅读有关through属性的更多信息:https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.manytomanyfield.through
祝你好运!

相关问题