6

私のDjangoモデルには、2つのフィールドname(通常のCharField)とslug、フィールド定義で渡されたフィールド名に基づいてスラッグを生成するカスタムフィールドがあります。この場合はこれを使用nameします。

まず、モデルにはnameフィールドのみがあり、対応する移行とすべてが含まれていました。次に、slugフィールドを追加する必要があったので、南の規則に従って、でスラッグフィールドを追加しunique=False、スキーマ移行を作成してから、データ移行unique=Trueを作成し、この最後の変更に対してを設定して、別の移行を作成しました。

スラッグの値はモデルの保存時に生成されるため、データ移行のメソッドで行ったのは、各インスタンスでforwards返されたクエリセットを繰り返し処理しorm['myapp.MyModel'].objects.all()、メソッドを呼び出すことでした。save()

ただし、スラッグフィールドの値は生成されません。IPythonセッションでは、同じことを行いましたが、モデルをとして参照しfrom myapp.models import MyModel、機能しました。いくつかのデバッグステートメントを使用してtype、Southのorm dictによって返されたモデルのを出力すると、実際のクラスが表示されます。これは、Southによってオンザフライで構築された偽のモデルではないようです。

slugフィールドは、pre_saveメソッドのときにその値を作成します。データ移行中に強制的に呼び出されるようにするにはどうすればよいですか?後のスキーマ移行でインデックスが適用されるときに、列に重複する値が含まれないように、値の一意性を確認する必要があります。

ありがとう!

ところで:スラッグフィールドクラスは定義しているsouth_field_tripleので、サウスはそれでうまく機能します。

編集私の答えを見てください。しかし、答えのように、それはハックのように感じます。これを行うためのより良い/正しい方法はありますか?

4

2 に答える 2

4

一般に、フィールドの内容を生成するコードは、移行時にできるだけ厳密に複製する必要があります (意図的なコード複製のまれな例です)。あなたのアプローチのコードは、たとえそれが機能したとしても、移行の実行時に定義されたように pre_save を呼び出します。これは、移行が作成されたときのモデルの状態で変更されたり、失敗したりする可能性があります (そうでない他のフィールドに依存する場合があります)。より早い時間に存在するなど)。

したがって、あなたの例での正しいアプローチは、SlugField の pre_save メソッドで行われるように、直接 slugify() を使用することです。

from django.template.defaultfilters import slugify

class Migration(DataMigration):

    def forwards(self, orm):
        "Write your forwards methods here."

        for myobj in orm['myapp.MyModel'].objects.all():
            myobj.slug = slugify(myobj.otherfield)
            myobj.save()
于 2012-11-13T09:12:02.107 に答える
1

モデルフィールドインスタンスを取得してpre_save直接呼び出すことで、これを一時的に解決しました。

class Migration(DataMigration):

    def forwards(self, orm):
        "Write your forwards methods here."
        # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
        for myobj in orm['myapp.MyModel'].objects.all():
            slug_field = myobj._meta.get_field_by_name('slug')[0]
            myobj.slug = slug_field.pre_save(myobj, add=False)
            myobj.save()

ただし、カスタムフィールドでこれを考慮するのは面倒です...

于 2012-07-16T14:01:55.657 に答える