Django save行为随机

2024-03-28 23:24:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个与一些资源对象有M2M关系的故事模型。一些资源对象缺少一个名称,因此我想将故事的标题复制到指定的资源对象。你知道吗

这是我的代码:

from collector import models
from django.core.paginator import Paginator

paginator = Paginator(models.Story.objects.all(), 1000)

def fix_issues():
    for page in range(1, paginator.num_pages + 1):
        for story in paginator.page(page).object_list:
            name_story = story.title
            for r in story.resources.select_subclasses():
                if r.name != name_story:
                    r.name = name_story
                    r.save()
                    if len(r.name) == 0:
                        print("Something went wrong: " + name_story)
        print("done processing page %s out of %s" % (page, paginator.num_pages))

fix_issues()

我需要使用分页器,因为我要处理一百万个对象。奇怪的是,在调用fix\u issues()之后,我的大约一半没有名字的资源现在有了正确的名字,而另一半仍然没有名字。我可以一次又一次地调用fix\u issues(),每次有更多的对象收到一个名称。这对我来说真的很奇怪,为什么一个对象第一次不更新,第二次才更新?你知道吗

其他信息:

  • “出事了:”信息从未打印过。你知道吗
  • 我使用django model utils中的select_子类来迭代所有资源(任何类型)。你知道吗
  • 那个故事.标题从不为空。你知道吗
  • 当我运行这些命令时,不会打印错误消息。你知道吗
  • 我没有覆盖资源模型的save方法(只有故事模型的save方法)。你知道吗
  • 我试着用@事务处理.atomic但结果是一样的。你知道吗

我的型号:

class Resource(models.Model):
    name = models.CharField(max_length=200)
    # Important for retrieving the correct subtype.
    objects = InheritanceManager()

    def __str__(self):
        return str(self.name)


class CustomResource(Resource):
    homepage = models.CharField(max_length=3000, default="", blank=True, null=True)


class Story(models.Model):
    url = models.URLField(max_length=3000)
    resources = models.ManyToManyField(Resource)
    popularity = models.FloatField()

    def _update_popularity(self):
        self.popularity = 3

    def save(self, *args, **kwargs):
        super(Story, self).save(*args, **kwargs)
        self._update_popularity()
        super(Story, self).save(*args, **kwargs)

文档对于选择的\u子类: http://django-model-utils.readthedocs.io/en/latest/managers.html#inheritancemanager

进一步调查: 我认为select\u子类可能没有返回所有的对象。现在每个故事都有一个资源。所以很容易检查select\u子类是否总是返回一个项。这是我使用的函数:

def find_issues():
    for page in range(1, paginator.num_pages + 1):
        for story in paginator.page(page).object_list:
            assert(len(story.resources.select_subclasses()) == 1)
        print("done processing page %s out of %s" % (page, paginator.num_pages))

但同样的,它执行起来没有任何问题。所以我不认为select\u子类是罪魁祸首。我还查了一下paginator.num\u页是正确的。如果我除以1000(每页项目数),我就得到了我数据库中的故事数。你知道吗


Tags: 对象nameinselfformodelssavedef
1条回答
网友
1楼 · 发布于 2024-03-28 23:24:23

我想我知道发生了什么:

Paginator加载一个Queryset并给出前n项。我处理这些并更新一些值。但在下一次迭代中,queryset中项目的顺序会发生变化(因为我更新了其中一些项目,并且没有定义顺序)。所以我跳过了现在在第一页的项目。我可以通过指定一个顺序(例如pk)来避免它。你知道吗

如果你认为我错了,请告诉我。否则我会接受这个正确答案。非常感谢。你知道吗

相关问题 更多 >