Django-South를 사용하여 모델 필드의 이름을 바꾸는 방법?


209

모델의 특정 필드 이름을 변경하고 싶습니다.

class Foo(models.Model):
    name = models.CharField()
    rel  = models.ForeignKey(Bar)

로 변경해야합니다.

class Foo(models.Model):
    full_name     = models.CharField()
    odd_relation  = models.ForeignKey(Bar)

South를 사용하여 가장 쉬운 방법은 무엇입니까?


7
모델 필드 대신 모델 이름을 바꾸려면 stackoverflow.com/questions/2862979/… 도 참조하십시오 .
기계 달팽이

답변:


230

db.rename_column기능을 사용할 수 있습니다 .

class Migration:

    def forwards(self, orm):
        # Rename 'name' field to 'full_name'
        db.rename_column('app_foo', 'name', 'full_name')




    def backwards(self, orm):
        # Rename 'full_name' field to 'name'
        db.rename_column('app_foo', 'full_name', 'name')

첫 번째 인수 db.rename_column는 테이블 이름이므로 Django가 테이블 이름을 만드는 방법을 기억하는 것이 중요 합니다 .

Django는 모델 클래스의 이름과이를 포함하는 앱에서 데이터베이스 테이블의 이름을 자동으로 파생시킵니다. 모델의 데이터베이스 테이블 이름은 모델의 "앱 레이블"(manage.py startapp에 사용 된 이름)을 모델의 클래스 이름에 밑줄로 결합하여 구성됩니다.

같은 프로젝트 아이템으로 사용하여 멀티 말로, 낙타 맡았다 모델 이름을 가지고있는 경우에, 테이블 이름이 될 것입니다 app_projectitem(즉, 밑줄 사이에 삽입되지 않습니다 projectitem비록 그들이 낙타 맡았다 있습니다).


2
name \ full_name에서는 작동하지만 관계 필드에서는 작동하지 않습니다.
조나단

23
중요 사항 : 이것을 사용하려면 "app_foo"가 데이터베이스 테이블 이름인지 확인하십시오. 예를 들어 "mainapp_profile", "name"은 데이터베이스의 이전 열 이름 (모델 필드 이름이 아님), 예를 들어 : "user_id"및 "full_name"은 열이 가질 새 이름 (필드 이름이 아닌 데이터베이스 열)입니다. db.rename_column ( 'mainapp_profile', 'user_id', 'new_user_id') 또한 외래 키를 다루는 경우 이름을 바꿀 때 "_id"부분이 있어야합니다.
Gezim

3
이 db.rename_column을 수동으로 수행하는 경우 나중에 백업을 정리하기 위해 가짜 스키마 마이그레이션을 수행해야 할 수도 있습니다. 먼저 열 이름을 바꾸어 변경 사항을 마이그레이션하십시오. 그런 다음 업데이트 된 이름을 갖도록 모델을 수정 한 다음 ./manage.py schemamigration app --auto && ./manage.py migrate app --fake를 수행하십시오.
jimbob 박사

24
./manage.py schemamigration my_app renaming_column_x --empty를 사용하여 빈 마이그레이션을 만들고 코드를 넣을 수도 있습니다
Ilian Iliev

11
--empty는 별 도움이되지 않지만 대신 --auto를 사용하여 생성 된 마이그레이션을 수정하십시오. 이렇게하면 다음에 models.py를 마이그레이션 할 때 필드가 청구되지 않습니다.
yasc 2016 년

39

내가하는 일은 다음과 같습니다.

  1. 모델에서 열 이름을 변경하십시오 (이 예에서는 myapp/models.py).
  2. 운영 ./manage.py schemamigration myapp renaming_column_x --auto

참고 renaming_column_x로 원하는 것을 지정할 수 있습니다. 마이그레이션 파일에 설명적인 이름을 지정하는 방법 일뿐입니다.

그러면 myapp/migrations/000x_renaming_column_x.py이전 열을 삭제하고 새 열을 추가하는 파일이 생성 됩니다.

이 파일의 코드를 수정하여 마이그레이션 동작을 간단한 이름 바꾸기로 변경하십시오.

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Renaming column 'mymodel.old_column_name' to 'mymodel.new_column_name'
        db.rename_column(u'myapp_mymodel', 'old_column_name', 'new_column_name')

    def backwards(self, orm):
        # Renaming column 'mymodel.new_column_name' to 'mymodel.old_column_name'
        db.rename_column(u'myapp_mymodel', 'new_column_name', 'old_column_name')

명령에서 열 이름은 무엇입니까? x또는 column_x?
andilabs

언급 한 명령의 일부는 마이그레이션 이름을 지정하는 데 사용되며 원하는대로 지정할 수 있습니다. 열 이름은 편집 할 때 마이그레이션 파일에서 지정해야합니다.
donturner

2
--auto마이그레이션을 먼저 만드는 것이 좋습니다. 이 마이그레이션 만있는 경우 발생하는 사우스 ORM 냉동고 문제, 방지 forwardsbackwards방법,하지만 냉동 포함하지 않는 model개체를.
mwcz

'이 필드를 제거하고 있으므로 반드시 기본값을 지정해야합니다'라는 남쪽의 질문에 어떻게 대답합니까?
브라이스

3
이 방법의 한 가지 문제 는 열과 관련된 제약 조건의db.rename_column 이름을 바꾸지 않는다는 것 입니다. 마이그레이션은 여전히 ​​작동하지만 이전 열 이름의 이름을 따서 제약 조건이 있습니다. 고유 제약 조건이있는 열이 있었고이 방법을 사용하여 이름을 바꾸고 고유 제약 조건이 여전히 존재하고 오류가 있는지 테스트했지만 제약 조건 자체의 이름은 여전히 ​​이전 열 이름을 사용하고 있습니다. 아마도 명백 하고 그것을했을 것입니다. 그러나 나는 sjh의 해결책으로 가기로 결정했습니다. db.delete_uniquedb.create_unique
Louis

15

db.rename 열에 대해 몰랐지만 편리하게 들리지만 과거에는 새 열을 하나의 스키마 마이그레이션으로 추가 한 다음 값을 새 필드로 이동하기 위해 데이터 마이그레이션을 만든 다음 이전 열을 제거하는 두 번째 스키마 마이그레이션을 만들었습니다.


나도. schema-data-schema 기술의 문제점은 필드 / 모델의 이름이 달라진다는 것입니다. 디스패처를 활성화하기 위해 표준 이름을 사용하는 경우 때때로 문제가됩니다.
Jonathan

방금 시도했지만 이름이 충돌하여 작동하지 않았습니다. 나는 똑같은 FK를 가지고 있지만 이름이 다릅니다. 확인하지 않았습니다. 따라서이 작업을 수행하지 마십시오.
Gezim

2
@jonathan, 그는 다른 이름을 원한다! ... @pilgrim, 코드를 게시 할까? 이번 주에 여러 번이 작업을 수행했습니다. 모델의 유효성이 검사되지 않으면 남쪽에서 마이그레이션을 생성하지 않습니다.
sjh

그것은 작동하지만 다른 사람들이 제안한 'rename_column'보다 느릴 것입니다. MySQL이 "ALTER TABLE ... rename column"(또는 그 무엇이든)을 매우 빠르게 수행 할 수 있다는 것을 알고 있습니다.
Rory

1
@Rory db.rename_column는 제약 조건의 이름을 바꾸지 않으므로 수동으로 처리해야합니다. 잊어 버린 경우 이전 열 이름을 여전히 사용하는 제약 조건이있을 수 있다는 점을 제외하고 마이그레이션이 작동합니다. 문제가 단지 장식적인 것인지 또는 제약 조건을 조작하거나 제거해야하는 향후 마이그레이션에서이 문제를 찾을 수 없는지 확실하지 않습니다. 여하튼, sjh가 제안한 것처럼 여기에서 수행하는 것이 안전한 방법입니다. South가 알아 내야 할 것을 알아낼 수 있습니다.
Louis

10

Django 1.7에는 마이그레이션 이 도입 되었으므로 이제 마이그레이션 을 관리하기 위해 추가 패키지를 설치할 필요가 없습니다.

모델 이름을 바꾸려면 먼저 빈 마이그레이션을 만들어야합니다.

$ manage.py makemigrations <app_name> --empty

그런 다음 마이그레이션 코드를 다음과 같이 편집해야합니다.

from django.db import models, migrations

class Migration(migrations.Migration):

dependencies = [
    ('yourapp', 'XXXX_your_previous_migration'),
]

operations = [
    migrations.RenameField(
        model_name='Foo',
        old_name='name',
        new_name='full_name'
    ),
    migrations.RenameField(
        model_name='Foo',
        old_name='rel',
        new_name='odd_relation'
    ),
]

그리고 나서 다음을 실행해야합니다.

$ manage.py migrate <app_name>

5

그냥 모델을 변경하고 makemigrations1.9에서 실행하십시오 .

Django는 사용자가 단일 필드를 삭제하고 생성했음을 자동으로 감지하여 다음을 묻습니다.

Did you rename model.old to model.new (a IntegerField)? [y/N]

예라고 말하면 올바른 마이그레이션이 생성됩니다. 마법.


0
  1. south프로젝트 설정 파일에서 설치된 앱에 추가 하십시오.
  2. 추가 / 수정 된 필드 / 테이블을 주석 처리하십시오.
  3. $ manage.py Schemamigration <app_name> --initial
  4. $ manage.py migrate <app_name> --Fake
  5. 필드의 주석을 해제하고 수정 된 필드를 작성하십시오
  6. $ manage.py Schemamigration --auto
  7. $ manage.py migrate <app_name>

'pycharm'을 사용하는 경우 'manage.py'대신 'ctrl + shift + r'을 사용하고 매개 변수에 'shift'를 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.