Django 保存随机行为
Django save behaving randomly
我有一个与某些资源 object 具有 M2M 关系的故事模型。某些资源 object 缺少名称,因此我想将故事的标题复制到分配的资源 object 中。
这是我的代码:
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()
我需要使用分页器,因为我要处理一百万 objects。奇怪的是,在调用 fix_issues() 之后,大约一半没有名称的资源现在有了正确的名称,而另一半仍然没有名称。我可以一次又一次地调用 fix_issues(),每次都有更多的 object 收到一个名字。这对我来说真的很奇怪,为什么 object 不是第一次更新而是第二次更新?
附加信息:
- "Something went wrong: " 消息从未 打印。
- 我正在使用 django-model-utils 中的 select_subclasses 来遍历所有资源(任何类型)。
- story.title 从不 为空。
- 当我运行这些命令时,没有打印错误信息。
- 我没有覆盖Resource模型的save方法(只覆盖了Story模型的save方法)
- 我尝试使用@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 没有 return 所有 object。现在每个故事都有一个资源。因此很容易检查 select_subclasses 总是 return 一项。这是我使用的功能:
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)来避免它。
如果您认为我错了,请告诉我。否则我会接受这个作为正确答案。谢谢。
我有一个与某些资源 object 具有 M2M 关系的故事模型。某些资源 object 缺少名称,因此我想将故事的标题复制到分配的资源 object 中。
这是我的代码:
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()
我需要使用分页器,因为我要处理一百万 objects。奇怪的是,在调用 fix_issues() 之后,大约一半没有名称的资源现在有了正确的名称,而另一半仍然没有名称。我可以一次又一次地调用 fix_issues(),每次都有更多的 object 收到一个名字。这对我来说真的很奇怪,为什么 object 不是第一次更新而是第二次更新?
附加信息:
- "Something went wrong: " 消息从未 打印。
- 我正在使用 django-model-utils 中的 select_subclasses 来遍历所有资源(任何类型)。
- story.title 从不 为空。
- 当我运行这些命令时,没有打印错误信息。
- 我没有覆盖Resource模型的save方法(只覆盖了Story模型的save方法)
- 我尝试使用@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 没有 return 所有 object。现在每个故事都有一个资源。因此很容易检查 select_subclasses 总是 return 一项。这是我使用的功能:
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)来避免它。
如果您认为我错了,请告诉我。否则我会接受这个作为正确答案。谢谢。