7

データベースには Django と South を使用しています。ここで、新しいモデルを参照して、既存のモデルに新しいモデルとフィールドを追加したいと考えています。例えば:

class NewModel(models.Model):
    # a new model
    # ... 

class ExistingModel(models.Model):
    # ... existing fields

    new_field = models.ForeignKey(NewModel)  # adding this now

ここで、South は明らかに、null 以外のフィールドを追加したことに文句を言い、1 回限りの値を入力するように求めてきました。しかし、私が本当に望んでいるのはNewModel、既存のインスタンスごとに新しいインスタンスを作成しExistingModelて、データベースの要件を満たすことです。それはどういうわけか可能ですか?

4

2 に答える 2

9

これを行う最も簡単な方法は、列を変更するスキーマ移行を作成してから、データ移行を作成して値を正しく入力することです。使用しているデータベースによっては、少し異なる方法でこれを行う必要があります。

スクライト

Sqlite の場合、リレーションにセンチネル値を追加し、datamigration を使用して問題なく入力できます。

0001_schema_migration_add_foreign_key_to_new_model_from_existing_model.py

from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):
    
    def forwards(self, orm):
        db.add_column('existing_model_table', 'new_model',
                      self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['appname.new_model']), keep_default=False)

0002_data_migration_for_new_model.py:

class Migration(DataMigration):
    
    def forwards(self, orm):
        for m in orm['appname.existing_model'].objects.all():
            m.new_model = #custom criteria here
            m.save()
    

これで問題なく動作します。

Postgres と MySQL

MySql では、有効なデフォルトを指定する必要があります。0が実際に有効な Foreignkey でない場合は、そのことを示すエラーが表示されます。

デフォルトの 1 にすることもできますが、それが有効な外部キーではない場合があります (環境が異なり、一部の環境が他のデータベースに公開されているため、私に起こりました。そのため、ID はめったに一致しません (クロス神が意図したように、データベースの識別)。

2 番目の問題は、South と MySQL がうまく連携しないことです。部分的には、MySQL には DDL トランザクションの概念がないためです。

必然的に直面するいくつかの問題 (上記のエラーやorm、SchemaMigration 内の項目を としてマークするよう求める South からのエラーを含む) を回避するには、上記のスクリプトを次no-dry-runのように変更する必要があります。0001

0001_schema_migration_add_foreign_key_to_new_model_from_existing_model.py

from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):
    
    def forwards(self, orm):
        id = 0
        if not db.dry_run:
            new_model = orm['appname.new_model'].objects.all()[0]
            if new_model:
                id = new_model.id
        db.add_column('existing_model_table', 'new_model',
                      self.gf('django.db.models.fields.related.ForeignKey')(default=id, to=orm['appname.new_model']), keep_default=False)

0002_data_migration_for_new_model.pyその後、通常どおりファイルを実行できます。

上記と同じ例を Postgres と MySql に使用することをお勧めします。最初の例では、Postgres で何の問題も覚えていませんが、2 番目の例は両方で動作することは確かです (テスト済み)。

于 2013-07-11T18:38:49.820 に答える
6

このシナリオでは、スキーマの移行を補完するデータ移行が必要です。

South には、ドキュメントでこれを達成する方法についての段階的なチュートリアルがあります

南部では、望ましい結果が 2 つまたは 3 つのスキーマ/データ移行にまたがることは珍しくありません。これは、1 つの大きなヒットで常に可能であるとは限らないためです (デフォルトのない null 以外の列の追加を許容するかどうかは、基礎となるデータベースに依存する場合があります) )。したがって、この場合、デフォルトを持つスキーマ移行を追加し、次にオブジェクト操作を伴うデータ移行、そして最終的なスキーマ移行を追加できます。

于 2013-04-11T19:20:39.973 に答える