python - Django 保存随机行为

标签 python django postgresql django-model-utils

我有一个与某些资源对象具有 M2M 关系的 Story 模型。一些资源对象缺少名称,因此我想将故事的标题复制到分配的资源对象。

这是我的代码:

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_issues() 之后,大约一半没有名称的资源现在有了正确的名称,而另一半仍然没有名称。我可以一次又一次地调用 fix_issues(),每次都有更多对象收到一个名称。这对我来说真的很奇怪,为什么一个对象不会在第一次更新而只在第二次更新?

附加信息:

  • “出了点问题:”消息从未打印出来。
  • 我正在使用 django-model-utils 中的 select_subclasses 来迭代所有资源(任何类型)。
  • story.title 从不为空。
  • 当我运行这些命令时,没有打印错误消息。
  • 我没有覆盖资源模型的保存方法(只覆盖了故事模型的保存方法)。
  • 我尝试使用@transaction.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)
select_subclasses 的

文档: http://django-model-utils.readthedocs.io/en/latest/managers.html#inheritancemanager

进一步调查: 我想也许 select_subclasses 没有返回所有的对象。现在每个故事都有一个资源。因此很容易检查 select_subclasses 是否总是返回一项。这是我使用的功能:

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_subclasses 是罪魁祸首。我还检查了 paginator.num_pages 是否正确,确实如此。如果我除以 1000(每页的项目数),我将得到我数据库中的准确故事数。

最佳答案

我想我知道发生了什么:

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

如果你认为我错了,请告诉我。否则我会接受这个作为正确答案。谢谢。

关于python - Django 保存随机行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40703808/

相关文章:

python - gremlinpython - 以字符串形式返回 id 和标签

python - 从一个子图中删除轴刻度

python - 在python中调用带括号和不带括号的函数有什么区别?

python - 从数据框中随机选择小时

django - 清理数据时附加到 ManyToMany 表单字段时出现问题

ruby-on-rails - 如何在 rails 中创建 postgres 触发器?

用于创建插入脚本的 SQL 脚本

Django-Oscar 覆盖模板标签

django - 在 django-tastypie 中返回 POST 数据

ruby-on-rails - AWS Rails Capistrano PG 部署错误