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(즉, 밑줄 사이에 삽입되지 않습니다 project및 item비록 그들이 낙타 맡았다 있습니다).


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 냉동고 문제, 방지 forwards및 backwards방법,하지만 냉동 포함하지 않는 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.