Pull to refresh

South — новый клёвый syncdb

Reading time3 min
Views26K
Я совсем недавно начал работать с Django и меня практически сразу же взбесила ущербная команда syncdb, которая ничего толком не синхронизирует, умеет лишь создавать таблицы для новых моделей.

А добавление или удаление полей в уже существующие модели превращается в настоящий pain in ass — приходится «подсматривать» за тем, как ORM создала бы таблицы заново (manage.py sqlall) и вручную делать ALTER TABLE для изменившихся столбцов таблиц.

То есть, ORM в Django так или иначе предполагает активный трах с SQL shell, потому что в процессе прототипирования эти поля в моделях изменяются просто пачками.

Погуглив, я нашел несколько способов автоматизации изменения схемы БД и в итоге остановился на South. Эта утилита автоматизирует процесс db schema migration. (а название утилиты, насколько я понял, обыгрывает термин «миграция» — ведь зимой все птицы летят на йух :)).

Я выбрал South из-за того, что оно хранит историю миграций и можно делать undo/redo, а так же корректировать код миграции руками.

Полный туториал можно почитать здесь: south.aeracode.org/wiki/Tutorial, я лишь вкратце поясню, как оно работает.

 

Установка


1. Сливаем svn'ом код утилиты отсюда: https://svn.aeracode.org/svn/south/trunk

2. Кладем его в python/lib/site-packages или еще куда-нибудь, где его будет видно

3. В settings.INSTALLED_APPS добавляем 'south'

4. Делаем привычный manage.py syncdb и видим, что он стал каким-то другим

 

Использование


Теперь представим ситуацию: в уже существующую модель нам надо добавить пару полей. К примеру, таких:

class CompanyProduct (models.Model):

  # .. бла-бла, какие-то старые поля ..

  download_url = models.URLField (
    u'Ссылка для скачивания',
    blank = True, null = True)

  system_requirements = models.TextField (
    u'Системные требования',
    blank = True, null = True)


* This source code was highlighted with Source Code Highlighter.


Создаём миграцию:

python manage.py startmigration [имя_вашего_app] add_download_section
  --add-field CompanyProduct.download_url
  --add-field CompanyProduct.system_requirements

Creating __init__.py in '[path_to_app]\migrations'...
Created 0001_add_download_section.py.


Применяем её:

python manage.py migrate [имя_вашего_app]

Running migrations for [имя_вашего_app]:
- Migrating forwards to 0001_add_download_section.
> [имя_вашего_app]: 0001_add_download_section
  = ALTER TABLE "products" ADD COLUMN "download_url" varchar(200) NULL; []
  = ALTER TABLE "products" ADD COLUMN "system_requirements" text NULL; []
- Loading initial data for [имя_вашего_app].


Движимые научным любопытством, смотрим, что нам сгенерил South в 0001_add_download_section.py:

from south.db import db
from django.db import models
from [имя_вашего_app].models import *

class Migration:
  
  def forwards(self):
    
    # Adding field 'CompanyProduct.download_url'
    db.add_column('products', 'download_url',
        models.URLField (u'Ссылка для скачивания', blank = True, null = True))
    
    # Adding field 'CompanyProduct.system_requirements'
    db.add_column('products', 'system_requirements',
        models.TextField (u'Системные требования', blank = True, null = True))
    
  
  def backwards(self):
    
    # Deleting field 'CompanyProduct.download_url'
    db.delete_column('products', 'download_url')
    
    # Deleting field 'CompanyProduct.system_requirements'
    db.delete_column('products', 'system_requirements')



Косяк


В моём случае напильником пришлось добавить вывод "# coding=utf-8" в начало миграционного скрипта (см. /south/management/commands/startmigration.py, строка 290), иначе он фейлился из-за unicode-строк в нём.
Tags:
Hubs:
+33
Comments34

Articles