기존에 값이 있는 db에 unique한 필드를 추가하고 migration을 하려고 하면 다음과 같은 내용이 나온다.
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>>
아무 값이나 추가하여도 migration은 잘 되지만 migrate시에 기존 값의 unique=True
가 충돌이 나서 migrate이 진행되지 않는다.
그동안은 꼼수로
null=True
로 migrate => shell에 들어가서 값 unique하게 변경 => 다시 unique=True
로 migarte
하는 과정을 거쳐서 진행하였는데, 장고 문서를 보던 중 migartion 파일에서 Runpython
을 활용해서 이를 해결할 수 있는 방법을 발견하여 사용해보았다.
장고 문서는 여기에서 확인이 가능하다.
1. 일단 unique=True
로 migration을 한다.
나는 ref_id
를 추가하는 마이그레이션 파일을 만들었다.
0002_xxxx
파일이 만들어진 것을 확인할 수 있다.
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2019-02-03 20:41
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('invests', '0001_xxxxxx'),
]
operations = [
migrations.AddField(
model_name='invest',
name='ref_id',
field=models.CharField(default='', max_length=255, unique=True),
),
]
2. 해당 migration 파일에서 unique=True
를 null=True
로 변경한다.
Runpython을 진행하기 전 해당 필드를 생성하기 위함이다. (그냥 null=True로 migration 한 이후에 나중에 model을 변경해도 무방하다.)
... # 위와 동일
operations = [
migrations.AddField(
model_name='invest',
name='ref_id',
field=models.CharField(default='', max_length=255, null=True),
),
]
3. 새로운 migartaion 파일을 생성하여 Runpython script를 넣어준다.
나는 0003_add_ref_id
라는 파일을 만들었다.
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2019-02-03 20:41
from __future__ import unicode_literals
from django.db import migrations, models
def get_tid(apps, schema_editor):
Mymodel = apps.get_model('app_name', 'MyModel')
for row in MyModel.objects.all():
# 여기에서 넣고싶은 값을 추가해준다. 나는 해당 모델이 fk로 가진 user id와 인스턴스의 id를 ref_id로 추가하였다.
row.ref_id = '{}-{}'.format(row.user.id, row.id)
row.save(update_fields=['ref_id'])
class Migration(migrations.Migration):
dependencies = [
# 위에서 생성된 migration 파일의 이름을 추가해준다.
('invests', '0002_xxxxxx'),
]
operations = [
migrations.RunPython(get_tid, reverse_code=migrations.RunPython.noop),
]
4. migrate
migration 파일을 만들고 (unique=True인 migration 파일이 새로 생성된다) migrate을 하면 정상적으로 migrate가 됨을 볼 수 있다.
# 새 migaration 파일 생성 (0004_xxxxx)
python manage.py makemigrations
# migrate
python manage.py migrate
'backend > django' 카테고리의 다른 글
Django: Filter with CharField length (0) | 2018.07.26 |
---|---|
Django: show invalid message in django loginform (0) | 2018.07.23 |
Django: add attrs to django form (0) | 2018.07.22 |
Django: channels 2.0 with nginx + daphne (0) | 2018.06.20 |
Django: use ckeditor in django - django ckeditor (0) | 2018.05.24 |