0

指定されたモデルに基づく一般化されたモデルが必要であることに気付きました。次の例は、私が何を意味するかを示しているはずです。

前:

class TextResult(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
    text = models.ForeignKey(Text)
    wpm = models.FloatField(default=0.0)
    accuracy = models.FloatField(default=1.0)

後:

class TypingResult(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
    wpm = models.FloatField(default=0.0)
    accuracy = models.FloatField(default=1.0)


class TextResult(TypingResult):
    text = models.ForeignKey(Text)

元のモデルにはすでにいくつかのデータがありますが、データを新しいモデル構造に移行する必要があります

4

1 に答える 1

0

次の回答は、この回答に基づいています( https://stackoverflow.com/a/44148102/4129587 )

これを達成するには、手動でデータ移行を行う必要があります

次の 5 つの基本的な移行手順により、目的の結果が得られます。

  1. 新しいモデルを作成するTypingResult
  2. TypingResult古いモデルの新しいモデルに対して null 許容の新しい外部キーを作成するTextResult
  3. すべての古い属性を新しいモデルの新しいインスタンスにコピーしますTypingResult
  4. 元のモデルから id を含む古い属性を削除します
  5. 外部キーを新しい主キーとして変更します

新しいモデルの自動生成された移行で移行を開始できる場合があります

次のコードは、自動生成された移行に基づいており、テスト済みです

from __future__ import unicode_literals

from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion

def copy_text_results_to_typing_results(apps, schema_editor):
    TypingResult = apps.get_model('testapp', 'TypingResult')
    TextResult = apps.get_model('testapp', 'TextResult')
    for text_result in TextResult.objects.all():
        copied_result = TypingResult()
        copied_result.user = text_result.user
        copied_result.wpm = text_result.wpm
        copied_result.accuracy = text_result.accuracy
        copied_result.save()
        text_result.typingresult_ptr = copied_result
        text_result.save()

class Migration(migrations.Migration):

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('testapp', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='TypingResult',
            fields=[
                ('id', models.AutoField(auto_created=True, 
                                        primary_key=True,
                                        serialize=False,
                                        verbose_name='ID')),
                ('wpm', models.FloatField(default=0.0)),
                ('accuracy', models.FloatField(default=1.0)),
                ('user', models.ForeignKey(default=1, 
                                           on_delete=django.db.models.deletion.CASCADE,
                                           to=settings.AUTH_USER_MODEL)),
            ],
        ),
        # add the foreign key for the new inherited model,
        # it is allowed to have null values since the actual values have to be
        # copied first to this, it will be changed later
        migrations.AddField(
            model_name='textresult',
            name='typingresult_ptr',
            field=models.OneToOneField(blank=True, null=True, to='testapp.TypingResult'),
        ),
        # copy the old values to the new inherited model
        migrations.RunPython(copy_text_results_to_typing_results),
        # remove the old id and the copied fields from the TextResult model
        migrations.RemoveField(
            model_name='textresult',
            name='accuracy',
        ),
        migrations.RemoveField(
            model_name='textresult',
            name='id',
        ),
        migrations.RemoveField(
            model_name='textresult',
            name='user',
        ),
        migrations.RemoveField(
            model_name='textresult',
            name='wpm',
        ),
        # alter the id of the inherited model to be the new primary key
        migrations.AlterField(
            model_name='textresult',
            name='typingresult_ptr',
            field=models.OneToOneField(auto_created=True,
                                       on_delete=django.db.models.deletion.CASCADE,
                                       parent_link=True,
                                       primary_key=True,
                                       serialize=False,
                                       to='testapp.TypingResult'),
        ),
    ]
于 2017-05-25T01:15:54.490 に答える