2016-07-04 1 views
1

あまりにも多くのことをやっているDjangoモデルがあります。ここにモデルの簡略化された例があります。基本的には、これは4種類の異なるタイプのEntityを表すことができ、他のエンティティを指す再帰的なForeignKeyとManyToManyの関係があります。Djangoモデルを分割するとき、データ移行中にForeignKeyとManyToMany関係を保持する方法は?

このプロジェクトは現在Django 1.8.xとPython 2.7.xを使用していますが、解決策が必要な場合はアップグレードできます。

class Entity(models.Model): 
    """ 
    Films, People, Companies, Terms & Techniques 
    """ 

    class Meta: 
     ordering = ['name'] 
     verbose_name_plural = 'entities' 

    # Types: 
    FILM = 'FILM' 
    PERSON = 'PERS' 
    COMPANY = 'COMP' 
    TERM = 'TERM' 
    TYPE_CHOICES = (
     (FILM, 'Film'), 
     (PERSON, 'Person'), 
     (COMPANY, 'Company'), 
     (TERM, 'Term/Technique'), 
    ) 

    created = models.DateTimeField(auto_now_add=True, auto_now=False) 
    updated = models.DateTimeField(auto_now_add=False, auto_now=True) 
    type = models.CharField(max_length=4, choices=TYPE_CHOICES, default=FILM) 
    slug = models.SlugField(blank=True, unique=True, help_text="Automatically generated") 
    name = models.CharField(max_length=256, blank=True) 
    redirect = models.ForeignKey('Entity', related_name='entity_redirect', blank=True, null=True, help_text="If this is an alias (see), set Redirect to the primary entry.") 
    cross_references = models.ManyToManyField('Entity', related_name='entity_cross_reference', blank=True, help_text="This is a 'see also' — 'see' should be performed with a redirect.") 
    [... and more fields, some of them type-specific] 

私はこれはかなり厄介であると認識し、私は「タイプ」を削除し、共通フィールドのすべてを抽象化EntityBaseクラスを作り、そして新しいFilmPersonCompany、およびTermモデルを作成したいのですが抽象基本クラスEntityBaseから継承します。

私が新しいモデルを作成したら、すべてのフィールドデータを新しいモデルに移動するためのデータ移行の書き方を理解していると思います。Entityからオブジェクトを反復し、typeでフィルタリングし、新しいモデル)... を除く ForeignKeyとManyToMany関係。たぶん私は間違った方法を考えているかもしれませんが、移行中に関係が指し示す新しいオブジェクトがまだ存在しない場合、これらの関係をどのように転送できますか?

私はこれが複数ステップの移行を意味すると思われますが、私はこれを行う正しい方法を考えていません。

+0

これについてもっと考えてみたら、私は[この人と同じ問題がある]ことを実感しました。(http://stackoverflow.com/questions/16310930/django-polymorphic-models-or-one-big-model)私は、モデルの概念の明確さを増すために、私が上に示唆したことをすれば、私に関係の問題を引き起こし、物事の終わりを見るだろうと思っています。いずれにしても、4つ以上のモデルにすべての関連する結果を照会する必要があるか、または 'django-gm2m'のようなものを試してみる必要があります。 – bobtiki

+0

(抽象的ではなく)具体的な継承に切り替えると、それらの問題を解決するように見えますが、[具体的な継承を使用することについての恐ろしい警告](http://stackoverflow.com/questions/16310930/django-polymorphic-models-私はちょうどそれをそのまま残して、タイプごとに不要なフィールドを隠すために私の管理コードを少しきれいにするべきでしょうか? – bobtiki

答えて

1

m2mとfkフィールドについては何も魔法はありません。これは私が...それは少し鈍いかもしれませんが、仕事を得るだろうたどる手順です:

  1. は、データベースのBACKKKUPPPPPPpppを作ります!
  2. 別のバックアップを作成してください!
  3. 新しいモデルと移行の作成
  4. 手動で新しいモデルを繰り返し、新しいモデルを1つ1つ更新します。 dbに何百万ものエントリがない限り、forループを恐れてはいけません。
  5. 冗長モデルやフィールドを削除してください。このためには、移行を行ってください。
  6. 移行はちょうどになるまで、それらのマイグレーションを実行します:)

実際には、これは「BACKKKUPPPPPPppp」からの復元の多くを意味しています。

の世話をするための一つの小さな事は:(モデルは保存最初にそのIDを取得しているため)モデルがまだ保存されていない場合

M2M分野は、任意の値を取得することはできません。私は手動移行で、のような何かをするだろう:もちろん

new_instance = NewModel() 
new_instance.somefield = "whatever" 
new_instance.meaning = 42 
.... 
new_instance.save() 
new_instance.that_m2m_field.add(some_related_obj) 

、あなたはモデルクラスのインポートについては、特にそのビットを詳細にthe docs読んで確認してください - あなたはそれfrom myapp.models import MyModelをインポートすることはできません、代わりにdo:

MyModel = apps.get_model("myapp", "MyModel") 

導入予定のモデル相続財産の可能性があります。一般的には、子モデルを操作し、必要に応じて/から親にアクセスする必要があります。親は暗黙のptr属性を介してアクセスできます。例ではentitybase_ptrなど(これは単なるOneToOneフィールドです)です。しかし、親から未知の子供まで、他の方向に進むのは簡単ではありません。なぜなら親は先験​​的に子供のクラスが何であるかを知っていないからです。

+0

さて、わかりました。だから基本的に私はすべての新しいモデルを作成してオブジェクトをマイグレーションしてから、すべてのオブジェクトをマイグレーションして元のモデルをリファレンスとして使って、どのオブジェクトが関連しているかを調べることができます。その後、オブジェクトの新しいインスタンスを(それはユニークなので、多分、スラグによって)見つけ、m2m関係を再追加します。 – bobtiki

+0

@bobtikiこれはもっとも一般的なケースです。実際には過剰な作業であることが多く、データ移行を実行している間に重複したフィールドまたは2つのフィールドを持つだけで、同じ結果が得られます。 – frnhr

関連する問題