私はいくつかのリソースオブジェクトに対してM2M関係のStoryモデルを持っています。 Resourceオブジェクトの中には名前がないものがあるので、Storyのタイトルを割り当てられたResourceオブジェクトにコピーしたい。私は百万のオブジェクトを扱っていますので、私はページネータを使用する必要がDjangoはランダムに振る舞いを保存します
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はではありません。は空です。
- これらのコマンドを実行すると、エラーメッセージは表示されません。
- リソースモデルの保存メソッド(Storyモデルのsaveメソッドのみ)をオーバーライドしませんでした。
- 私は@ transaction.atomicを使用しようとしましたが、結果は同じでした。
マイモデル:select_subclassesため
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)
ドキュメント: http://django-model-utils.readthedocs.io/en/latest/managers.html#inheritancemanager
さらなる調査: を私は多分select_subclassesは、すべてのオブジェクトを返さなかったことを考えました。現在、すべてのストーリーには正確に1つのリソースがあります。したがって、select_subclassesが常に1つの項目を返すことを確認するだけで十分でした。これは私が使用した関数です:
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で割った場合(ページあたりのアイテム)、私は自分のデータベースにある物語の数を正確に取得します。
モデルの詳細を表示する必要があります。ストーリーには既定の順序が定義されていますか? 'select_subclasses'は何をしますか?とにかく、ページネーターは本当に適切なツールではありません。 queryset ['iterator()'](https://docs.djangoproject.com/ja/1.10/ref/models/querysets/#iterator)メソッドを調べたいと思うかもしれません。それとは別に、おそらく 'update()'を使ってこれを行うもっと効率的な方法があります。 –
私は使用しているライブラリへのコードとリンクを追加しました。回避策を見つけることは私にとってはそれほど重要ではないが、私はむしろこのアプローチが失敗する理由を理解するだろう。しかし、ヒントのおかげで、()更新時に読んでください。 – user667804
私はこれが問題(または問題)100%だと言っているわけではありませんが、あなたのコードから飛び跳ねるものは、オーバーライドされたsaveメソッドで 'super()。save()'を2回呼び出しています。あなたは同じargsとkwargsでそれをやっているので、最初の 'save()'がそれらからsthをポップしたら、新しいparamsでsaveを再度呼び出します。どちらかといえば、どちらかと言えば、人気の更新前でも更新後でも1回だけ呼び出すことをお勧めします。また、あなたがそれに精通していない場合、M2Mリレーションは 'save()'メソッド内に保存されませんが、別の方法があります.Djangoドキュメントでそれを探します。 – makaveli