Используя юг для рефакторинга модели Django с наследованием

1.div p.bio {font-size: 14px}
#sidebar p {font-size: 12px}

Первая строка CSS может показаться более специфичной на первый взгляд, но на самом деле это вторая строка выше, которая будет более специфичной для размера шрифта вашего абзаца.

id более специфичен, чем class, который более специфичен, чем элемент.

2.p {font-size: 12px}
p.bio {font-size: 14px}

Вторая строка CSS (p.bio) более конкретна, чем первая, когда речь заходит о вашем абзаце class="bio".

уровень приоритета class выше, чем у элемента p.

32
задан Serjik 19 December 2015 в 08:34
поделиться

3 ответа

Ознакомьтесь с ответом Пола ниже для некоторых замечаний о совместимости с новыми версиями Django / South.


Это казалось интересной проблемой, и я становлюсь большим поклонником South, поэтому я решил немного разобраться в этом. Я построил тестовый проект на основе того, что вы описали выше, и успешно использовал Юг для выполнения миграции, о которой вы спрашиваете. Прежде чем мы перейдем к коду, сделаем несколько замечаний:

  • В документации South рекомендуется выполнять перенос схемы и перенос данных отдельно. Я последовал его примеру.

  • На бэкэнде Django представляет унаследованную таблицу, автоматически создавая поле OneToOne в наследующей модели.

  • Понимая это, наша миграция на юг должна правильно обрабатывать поле OneToOne вручную, однако, экспериментируя с этим, кажется, что South (или, возможно, сам Django) не может создать файл OneToOne для нескольких унаследованных таблиц с тем же именем. Из-за этого я переименовал каждую дочернюю таблицу в приложении movies / tv, чтобы она соответствовала ее собственному приложению (например, MovieVideoFile / ShowVideoFile).

  • Играя с фактическим кодом миграции данных, кажется, что Юг предпочитает создавать Сначала поле OneToOne, а затем назначьте ему данные. Присвоение данных полю OneToOne во время создания приводит к подавлению South. (Справедливый компромисс для всей крутизны Юга.)

Итак, сказав все это, я попытался вести журнал выдаваемых консольных команд. Я добавлю комментарии, если это необходимо. Окончательный код находится внизу.

История команд

django-admin.py startproject southtest
manage.py startapp movies
manage.py startapp tv
manage.py syncdb
manage.py startmigration movies --initial
manage.py startmigration tv --initial
manage.py migrate
manage.py shell          # added some fake data...
manage.py startapp media
manage.py startmigration media --initial
manage.py migrate
# edited code, wrote new models, but left old ones intact
manage.py startmigration movies unified-videofile --auto
# create a new (blank) migration to hand-write data migration
manage.py startmigration movies videofile-to-movievideofile-data 
manage.py migrate
# edited code, wrote new models, but left old ones intact
manage.py startmigration tv unified-videofile --auto
# create a new (blank) migration to hand-write data migration
manage.py startmigration tv videofile-to-movievideofile-data
manage.py migrate
# removed old VideoFile model from apps
manage.py startmigration movies removed-videofile --auto
manage.py startmigration tv removed-videofile --auto
manage.py migrate

Для экономии места, и поскольку модели неизменно выглядят одинаково в конце, я ' m будет демонстрироваться только с приложением «фильмы».

movies / models.py

from django.db import models
from media.models import VideoFile as BaseVideoFile

# This model remains until the last migration, which deletes 
# it from the schema.  Note the name conflict with media.models
class VideoFile(models.Model):
    movie = models.ForeignKey(Movie, blank=True, null=True)
    name = models.CharField(max_length=1024, blank=True)
    size = models.IntegerField(blank=True, null=True)
    ctime = models.DateTimeField(blank=True, null=True)

class MovieVideoFile(BaseVideoFile):
    movie = models.ForeignKey(Movie, blank=True, null=True, related_name='shows')

movies / migrations / 0002_unified-videofile.py (миграция схемы)

from south.db import db
from django.db import models
from movies.models import *

class Migration:

    def forwards(self, orm):

        # Adding model 'MovieVideoFile'
        db.create_table('movies_movievideofile', (
            ('videofile_ptr', orm['movies.movievideofile:videofile_ptr']),
            ('movie', orm['movies.movievideofile:movie']),
        ))
        db.send_create_signal('movies', ['MovieVideoFile'])

    def backwards(self, orm):

        # Deleting model 'MovieVideoFile'
        db.delete_table('movies_movievideofile')

movies / migration / 0003_videofile-to-movievideofile-data. py (перенос данных)

from south.db import db
from django.db import models
from movies.models import *

class Migration:

    def forwards(self, orm):
        for movie in orm['movies.videofile'].objects.all():
            new_movie = orm.MovieVideoFile.objects.create(movie = movie.movie,)
            new_movie.videofile_ptr = orm['media.VideoFile'].objects.create()

            # videofile_ptr must be created first before values can be assigned
            new_movie.videofile_ptr.name = movie.name
            new_movie.videofile_ptr.size = movie.size
            new_movie.videofile_ptr.ctime = movie.ctime
            new_movie.videofile_ptr.save()

    def backwards(self, orm):
        print 'No Backwards'

Юг - это круто!

Хорошо, стандартный отказ от ответственности: вы имеете дело с живыми данными. Здесь я привел вам рабочий код, но, пожалуйста, используйте - db-dry-run для проверки вашей схемы. Всегда делайте резервную копию, прежде чем что-либо делать, и в целом будьте осторожны.

УВЕДОМЛЕНИЕ О СОВМЕСТИМОСТИ

Я собираюсь сохранить исходное сообщение без изменений, но с тех пор Саут изменил команду manage.py startmigration на manage.py schemamigration .

py (миграция схемы)
from south.db import db
from django.db import models
from movies.models import *

class Migration:

    def forwards(self, orm):

        # Adding model 'MovieVideoFile'
        db.create_table('movies_movievideofile', (
            ('videofile_ptr', orm['movies.movievideofile:videofile_ptr']),
            ('movie', orm['movies.movievideofile:movie']),
        ))
        db.send_create_signal('movies', ['MovieVideoFile'])

    def backwards(self, orm):

        # Deleting model 'MovieVideoFile'
        db.delete_table('movies_movievideofile')

movies / migration / 0003_videofile-to-movievideofile-data.py (миграция данных)

from south.db import db
from django.db import models
from movies.models import *

class Migration:

    def forwards(self, orm):
        for movie in orm['movies.videofile'].objects.all():
            new_movie = orm.MovieVideoFile.objects.create(movie = movie.movie,)
            new_movie.videofile_ptr = orm['media.VideoFile'].objects.create()

            # videofile_ptr must be created first before values can be assigned
            new_movie.videofile_ptr.name = movie.name
            new_movie.videofile_ptr.size = movie.size
            new_movie.videofile_ptr.ctime = movie.ctime
            new_movie.videofile_ptr.save()

    def backwards(self, orm):
        print 'No Backwards'

Юг - это круто!

Хорошо, стандартный отказ от ответственности: вы имеете дело с живыми данными. Здесь я привел вам рабочий код, но, пожалуйста, используйте - db-dry-run для проверки вашей схемы. Всегда делайте резервную копию, прежде чем что-либо делать, и в целом будьте осторожны.

УВЕДОМЛЕНИЕ О СОВМЕСТИМОСТИ

Я собираюсь сохранить исходное сообщение без изменений, но с тех пор Саут изменил команду manage.py startmigration на manage.py schemamigration .

py (миграция схемы)
from south.db import db
from django.db import models
from movies.models import *

class Migration:

    def forwards(self, orm):

        # Adding model 'MovieVideoFile'
        db.create_table('movies_movievideofile', (
            ('videofile_ptr', orm['movies.movievideofile:videofile_ptr']),
            ('movie', orm['movies.movievideofile:movie']),
        ))
        db.send_create_signal('movies', ['MovieVideoFile'])

    def backwards(self, orm):

        # Deleting model 'MovieVideoFile'
        db.delete_table('movies_movievideofile')

movies / migration / 0003_videofile-to-movievideofile-data.py (миграция данных)

from south.db import db
from django.db import models
from movies.models import *

class Migration:

    def forwards(self, orm):
        for movie in orm['movies.videofile'].objects.all():
            new_movie = orm.MovieVideoFile.objects.create(movie = movie.movie,)
            new_movie.videofile_ptr = orm['media.VideoFile'].objects.create()

            # videofile_ptr must be created first before values can be assigned
            new_movie.videofile_ptr.name = movie.name
            new_movie.videofile_ptr.size = movie.size
            new_movie.videofile_ptr.ctime = movie.ctime
            new_movie.videofile_ptr.save()

    def backwards(self, orm):
        print 'No Backwards'

Юг - это круто!

Хорошо, стандартный отказ от ответственности: вы имеете дело с живыми данными. Здесь я привел вам рабочий код, но, пожалуйста, используйте - db-dry-run для проверки вашей схемы. Всегда делайте резервную копию, прежде чем что-либо делать, и в целом будьте осторожны.

УВЕДОМЛЕНИЕ О СОВМЕСТИМОСТИ

Я собираюсь сохранить исходное сообщение без изменений, но с тех пор Саут изменил команду manage.py startmigration на manage.py schemamigration .

но используйте - db-dry-run , чтобы проверить свою схему. Всегда делайте резервную копию, прежде чем что-либо делать, и в целом будьте осторожны.

УВЕДОМЛЕНИЕ О СОВМЕСТИМОСТИ

Я собираюсь сохранить исходное сообщение без изменений, но с тех пор Саут изменил команду manage.py startmigration на manage.py schemamigration .

но используйте - db-dry-run для проверки вашей схемы. Всегда делайте резервную копию, прежде чем что-либо делать, и в целом будьте осторожны.

УВЕДОМЛЕНИЕ О СОВМЕСТИМОСТИ

Я собираюсь сохранить исходное сообщение без изменений, но с тех пор Саут изменил команду manage.py startmigration на manage.py schemamigration .

49
ответ дан 27 November 2019 в 20:32
поделиться

Абстрактная модель

class VideoFile(models.Model):
    name = models.CharField(max_length=1024, blank=True)
    size = models.IntegerField(blank=True, null=True)
    ctime = models.DateTimeField(blank=True, null=True)
    class Meta:
        abstract = True

Может быть родовое отношение также будет вам полезно.

3
ответ дан 27 November 2019 в 20:32
поделиться

Я выполнил аналогичную миграцию и решил сделать это несколько раз. шаги. В дополнение к созданию нескольких миграций я также создал обратную миграцию, чтобы обеспечить откат, если что-то пойдет не так. Затем я взял несколько тестовых данных и перенес их вперед и назад, пока не убедился, что они выводятся правильно, когда я перешел вперед. Наконец, я перенес рабочий сайт.

1
ответ дан 27 November 2019 в 20:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: