모델 및 관계 필드의 이름을 바꾸기 위한 장고 마이그레이션 전략
기존 장고 프로젝트에서 여러 모델의 이름을 변경할 예정인데, 여기에는 제가 변경하고자 하는 모델과 외부 키 관계가 있는 모델이 많습니다.여러 번 마이그레이션해야 할 것은 확실하지만 정확한 절차는 모르겠습니다.
제가 장고 앱 내에서 다음 모델로 시작한다고 가정해 보겠습니다.myapp
:
class Foo(models.Model):
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
class AnotherModel(models.Model):
foo = models.ForeignKey(Foo)
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.ForeignKey(Foo)
is_ridonkulous = models.BooleanField()
이름을 변경합니다.Foo
모델은 이름이 정말 말이 안 되고 코드에 혼란을 일으키고 있기 때문입니다.Bar
훨씬 더 명확한 이름이 될 겁니다
Django 개발 문서에서 읽은 바로는 다음과 같은 마이그레이션 전략을 가정하고 있습니다.
1단계
정models.py
:
class Bar(models.Model): # <-- changed model name
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
class AnotherModel(models.Model):
foo = models.ForeignKey(Bar) # <-- changed relation, but not field name
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.ForeignKey(Bar) # <-- changed relation, but not field name
is_ridonkulous = models.BooleanField()
에 하십시오.AnotherModel
의 필드 foo
변되지않업관데됩니다트이계가로 됩니다.Bar
제 많이 이 을 델모로 안된다는 입니다. 제 추론은 한 번에 너무 많이 바꾸지 말아야 한다는 것이고 만약 이 필드 이름을 변경한다면.bar
저는 그 칼럼의 데이터를 잃을 위험을 감수할 것입니다.
2단계
빈 마이그레이션 만들기:
python manage.py makemigrations --empty myapp
3단계
을 합니다.Migration
를 추가할 수 있습니다.RenameModel
작업 목록에 대한 작업:
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RenameModel('Foo', 'Bar')
]
4단계
마이그레이션 적용:
python manage.py migrate
5단계
에서 관련 models.py
:
class Bar(models.Model):
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
class AnotherModel(models.Model):
bar = models.ForeignKey(Bar) # <-- changed field name
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
bar = models.ForeignKey(Bar) # <-- changed field name
is_ridonkulous = models.BooleanField()
6단계
다른 빈 마이그레이션 만들기:
python manage.py makemigrations --empty myapp
7단계
을 합니다.Migration
를 추가하기 작성한 입니다.RenameField
작업 목록과 관련된 필드 이름에 대한 작업:
class Migration(migrations.Migration):
dependencies = [
('myapp', '0002_rename_fields'), # <-- is this okay?
]
operations = [
migrations.RenameField('AnotherModel', 'foo', 'bar'),
migrations.RenameField('YetAnotherModel', 'foo', 'bar')
]
8단계
두 번째 마이그레이션 적용:
python manage.py migrate
새 변수 이름을 반영하도록 나머지 코드(보기, 양식 등)를 업데이트하는 것 외에, 기본적으로 새로운 마이그레이션 기능이 작동하는 방식이 이와 같습니까?
또한, 이것은 많은 단계처럼 보입니다.마이그레이션 작업을 어떤 방식으로 압축할 수 있습니까?
감사합니다!
그래서 제가 이것을 시도했을 때, 당신은 3 - 7단계를 요약할 수 있는 것처럼 보입니다.
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RenameModel('Foo', 'Bar'),
migrations.RenameField('AnotherModel', 'foo', 'bar'),
migrations.RenameField('YetAnotherModel', 'foo', 'bar')
]
admin.py 및 이전 마이그레이션 파일(!)과 같이 가져온 이름을 업데이트하지 않으면 몇 가지 오류가 발생할 수 있습니다.
업데이트: Seasaro에서 언급했듯이, Django의 최신 버전은 일반적으로 모델의 이름이 바뀌었는지 감지하고 물어볼 수 있습니다.그러니 시도해 보세요manage.py makemigrations
먼저 마이그레이션 파일을 확인합니다.
처음에는 4단계까지 마이그레이션이 잘 이루어졌기 때문에 Fiver의 방법이 나에게 효과가 있다고 생각했습니다.그러나 'ForeignKeyField(Foo)'를 'ForeignKeyField(Bar)'로 암시적으로 변경한 내용은 마이그레이션과 관련이 없습니다.관계 필드의 이름을 바꾸려고 할 때 마이그레이션이 실패한 이유입니다(5-8단계).이는 제 경우 'Another Model'과 'Yet Another Model'이 다른 앱에 설치되어 있기 때문일 수 있습니다.
그래서 다음 단계를 수행하여 모델과 관계 필드의 이름을 변경할 수 있었습니다.
저는 이것과 특히 오트란저의 속임수에서 그 방법을 수정했습니다.
Fiver처럼 제 앱에 있습니다.
class Foo(models.Model):
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
그리고 내 다른 앱에서는:
class AnotherModel(models.Model):
foo = models.ForeignKey(Foo)
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.ForeignKey(Foo)
is_ridonkulous = models.BooleanField()
1단계:
모든 OneToOneField(Foo) 또는 ForeignKeyField(Foo)를 IntegerField()로 변환합니다. 이렇게 하면 관련 Foo 개체의 ID가 정수 필드 값으로 유지됩니다.
class AnotherModel(models.Model):
foo = models.IntegerField()
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.IntegerField()
is_ridonkulous = models.BooleanField()
그리고나서
python manage.py makemigrations
python manage.py migrate
2단계: (Fiver의 2-4단계와 같이)
모델 이름 변경
class Bar(models.Model): # <-- changed model name
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
빈 마이그레이션 만들기:
python manage.py makemigrations --empty myapp
그런 다음 다음과 같이 편집합니다.
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RenameModel('Foo', 'Bar')
]
결국.
python manage.py migrate
3단계:
IntegerField()를 새 막대 모델을 사용하여 이전 ForeignKeyField 또는 OneToOneField로 변환합니다.(이전 정수 필드는 id를 저장하고 있었기 때문에 장고는 그것을 이해하고 연결을 다시 설정하는 것이 멋집니다.)
class AnotherModel(models.Model):
foo = models.ForeignKey(Bar)
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.ForeignKey(Bar)
is_ridonkulous = models.BooleanField()
다음을 수행합니다.
python manage.py makemigrations
이 단계에서는 모든 새 마이그레이션을 수정하고 모델 이름 바꾸기 Foo-> Bar 마이그레이션에 대한 종속성을 추가해야 합니다.따라서 다른 앱에 다른 모델과 다른 모델이 모두 있는 경우 다른 앱에서 생성된 마이그레이션은 다음과 같아야 합니다.
class Migration(migrations.Migration):
dependencies = [
('myapp', '00XX_the_migration_of_myapp_with_renamemodel_foo_bar'),
('myotherapp', '00xx_the_migration_of_myotherapp_with_integerfield'),
]
operations = [
migrations.AlterField(
model_name='anothermodel',
name='foo',
field=models.ForeignKey(to='myapp.Bar'),
),
migrations.AlterField(
model_name='yetanothermodel',
name='foo',
field=models.ForeignKey(to='myapp.Bar')
),
]
그리고나서
python manage.py migrate
4단계:
결국 필드 이름을 변경할 수 있습니다.
class AnotherModel(models.Model):
bar = models.ForeignKey(Bar) <------- Renamed fields
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
bar = models.ForeignKey(Bar) <------- Renamed fields
is_ridonkulous = models.BooleanField()
자동 이름 바꾸기를 수행합니다.
python manage.py makemigrations
(장고는 모델 이름을 실제로 바꿨는지 물어봅니다. 예라고 대답하십시오.)
python manage.py migrate
그게 다야!
이것은 장고 1.8에서 작동합니다.
현재버에전서는이모델수실있다바습니행할꾸고름을을 실행할 수 .python manage.py makemigrations
그런 다음 django는 모델의 이름을 변경할지 여부를 묻고 yes를 선택하면 모든 이름 변경 프로세스가 자동으로 수행됩니다.
저는 같은 일을 하고 따라야 했습니다.저는 모델을 한꺼번에 변경했습니다(Fiver의 답변에서 1단계와 5단계를 함께 변경했습니다).그런 다음 스키마 마이그레이션을 생성했지만 다음과 같이 편집했습니다.
class Migration(SchemaMigration):
def forwards(self, orm):
db.rename_table('Foo','Bar')
def backwards(self, orm):
db.rename_table('Bar','Foo')
이것은 완벽하게 작동했습니다.기존 데이터가 모두 표시되고 다른 테이블은 모두 Bar fine을 참조했습니다.
여기서: https://hanmir.wordpress.com/2012/08/30/rename-model-django-south-migration/
Django 1.10의 경우 MakeMigrations와 Migration을 실행하기만 하면 두 개의 모델 클래스 이름(ForeignKey와 데이터 포함)을 변경할 수 있었습니다.Make migrations 단계에서는 테이블 이름을 변경하고 싶다는 것을 확인해야 했습니다.마이그레이션은 문제 없이 테이블 이름을 변경했습니다.
그런 다음 ForeignKey 필드의 이름을 일치하도록 변경했고 Makeimigrations에서 이름을 변경할 것인지 확인하라는 요청을 다시 받았습니다.변경한 것보다 마이그레이션합니다.
그래서 저는 이것을 특별한 파일 편집 없이 두 단계로 나누었습니다.@wasibigeek가 언급한 바와 같이 admin.py 파일을 변경하는 것을 잊어버려서 처음에는 오류가 발생했습니다.
저는 또한 v.thory가 설명한 것처럼 문제에 직면했고, 그의 접근 방식이 매우 유용하지만 Fiver가 1~4단계 없이 설명한 것처럼 5~8단계로 압축될 수 있는 더 적은 단계로 요약될 수 있다는 것을 알게 되었습니다. 단, 7단계는 저의 아래 3단계로 변경되어야 합니다.전체 단계는 다음과 같습니다.
1단계: 모델에서 관련 필드 이름을 편집합니다.파이의
class Bar(models.Model):
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
class AnotherModel(models.Model):
bar = models.ForeignKey(Bar) # <-- changed field name
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
bar = models.ForeignKey(Bar) # <-- changed field name
is_ridonkulous = models.BooleanField()
2단계: 빈 마이그레이션 만들기
python manage.py makemigrations --empty myapp
3단계: 2단계에서 생성한 마이그레이션 파일의 마이그레이션 클래스 편집
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='AnotherModel',
name='foo',
field=models.IntegerField(),
),
migrations.AlterField(
model_name='YetAnotherModel',
name='foo',
field=models.IntegerField(),
),
migrations.RenameModel('Foo', 'Bar'),
migrations.AlterField(
model_name='AnotherModel',
name='foo',
field=models.ForeignKey(to='myapp.Bar'),
),
migrations.AlterField(
model_name='YetAnotherModel',
name='foo',
field=models.ForeignKey(to='myapp.Bar'),
),
migrations.RenameField('AnotherModel', 'foo', 'bar'),
migrations.RenameField('YetAnotherModel', 'foo', 'bar')
]
4단계: 마이그레이션 적용
python manage.py migrate
다 했어요.
추신: 저는 장고 1.9에 대해 이 접근법을 시도했습니다.
단지 확인하고 ceasaro 코멘트를 추가하고 싶을 뿐입니다.Django 2.0은 이제 자동으로 이것을 수행하는 것 같습니다.
저는 장고 2.2.1에 있습니다. 모델 이름을 바꾸고 실행하기 위해 해야 할 일이 전부였습니다.makemigrations
.
여기서 특정 클래스의 이름을 에서 변경했는지 묻습니다.A
로.B
저는 예를 선택하고 마이그레이션을 실행했고 모든 것이 작동하는 것 같습니다.
참고 프로젝트/마이그레이션 폴더 내의 파일에서 이전 모델 이름을 바꾸지 않았습니다.
저는 장고 버전 1.9.4를 사용하고 있습니다.
다음 단계를 수행했습니다.
방금 모델 이름을 oldName에서 NewNameRun으로 변경했습니다.python manage.py makemigrations
을 요구할 것입니다.Did you rename the appname.oldName model to NewName? [y/N]
Y를 선택합니다.
달려.python manage.py migrate
그리고 그것은 당신에게 요구할 것입니다.
다음 내용 유형은 오래되어 삭제해야 합니다.
appname | oldName
appname | NewName
외부 키에 의해 이러한 콘텐츠 유형과 관련된 모든 개체도 삭제됩니다.이러한 콘텐츠 유형을 삭제하시겠습니까?확실하지 않으면 '아니오'라고 대답합니다.
Type 'yes' to continue, or 'no' to cancel: Select No
기존의 모든 데이터 이름을 변경하고 새 명명된 테이블로 마이그레이션합니다.
데이터베이스에 오래된 테이블 이름을 남기는 마이그레이션 이름 변경과 관련하여 문제(각 django 1.x)를 발견했습니다.
장고는 오래된 테이블에서 아무것도 시도하지 않고 자신의 모델 이름만 바꿉니다.외부 키 및 일반적인 인덱스에 대한 동일한 문제는 장고에 의해 적절하게 추적되지 않습니다.
가장 간단한 솔루션(해결 방법):
class Foo(models.Model):
name = models.CharField(unique=True, max_length=32)
...
Bar = Foo # and use Bar only
실제 솔루션(모든 인덱스, 제약 조건, 트리거, 이름 등을 2개의 커밋으로 쉽게 전환할 수 있는 방법이지만 오히려 더 작은 테이블에 사용할 수 있습니다):
커밋 A:
- 이전 모델과 동일한 모델 생성
# deprecated - TODO: TO BE REMOVED
class Foo(model.Model):
...
class Bar(model.Model):
...
- 모델에 새 모 과 작 도 록 하 드 코 환
Bar
(스키마의 모든 관계 포함)
을 준비합니다.RunPython
Bar로 Bar 포함)id
푸(Foo)foo)s.
- 선택적 최적화(더 큰 테이블에 필요한 경우)
커밋 B: (서두르지 말고 팀 전체가 마이그레이션될 때 수행)
- 모델의
Foo
추가 정리:
- 이주에 대한 탄압.
장고의 버그:
몇 개의 테이블 이름을 변경해야 했습니다.그러나 장고는 단 하나의 모델 이름 변경만 확인했습니다.Django가 모델을 너무 많이 추가한 다음 제거하기 때문에 발생했습니다.각 쌍에 대해 동일한 앱의 필드와 필드가 동일한지 확인합니다.테이블 이름을 바꿀 테이블에 대한 외부 키가 없는 테이블 하나만 있습니다(외부 키에는 모델 클래스 이름이 포함됨).즉, 필드 변경이 없는 테이블은 하나뿐입니다.그것이 주목받은 이유입니다.
따라서 한 번에 하나의 테이블 이름을 변경하고 모델 클래스 이름을 변경하는 것이 해결책입니다.models.py
, 마도아.views.py
이름(, 이름 의 다른합니다.그런 다음 코드에서 다른 참조(모델 클래스 이름, 관련(쿼리) 이름, 변수 이름)를 검사합니다.필요한 경우 마이그레이션을 수행합니다.그런 다음 선택적으로 이러한 모든 마이그레이션을 하나로 결합합니다(가져오기도 복사해야 함).
저는 이 답변에 대한 그의 논평에 대해 @ceasaro 단어를 만들 것입니다.
최신 버전의 장고는 변경 사항을 감지하고 수행된 작업에 대해 물어볼 수 있습니다.또한 장고는 일부 마이그레이션 명령의 실행 순서를 혼합할 수도 있습니다.
사항을 하고 작은변사적실고행것것다현입니명할이는하용하경항을다▁it▁and것▁run▁small▁to▁be를 실행하는 이 현명할 것입니다.makemigrations
그리고.migrate
오류가 발생하면 마이그레이션 파일을 편집할 수 있습니다.
오류를 방지하기 위해 일부 행의 실행 순서를 변경할 수 있습니다.
2023년 업데이트:
- 모델 이름 바꾸기 Foo->bar
- 려달을 합니다.
makemigrations
- 관련 모델의 필드 이름 바꾸기 foo->bar
- 려달을 합니다.
makemigrations
- 마이그레이션 및 즐기십시오.
모델과 관련 필드의 이름을 동시에 변경하면 이전 모델의 이름을 변경하는 대신 삭제되고 새 모델이 생성됩니다.
PyCharm과 같은 좋은 IDE를 사용하는 경우 모델 이름을 마우스 오른쪽 버튼으로 클릭하고 리팩터 -> 이름 바꾸기를 수행할 수 있습니다.이렇게 하면 모델을 참조하는 모든 코드를 검토하는 수고를 덜 수 있습니다.그런 다음 마이그레이션 만들기 및 마이그레이션을 실행합니다.장고 2+는 간단히 이름 변경을 확인할 것입니다.
저는 장고를 버전 10에서 버전 11로 업그레이드했습니다.
sudo pip install -U Django
(-U
("업그레이드"용) 문제를 해결했습니다.
언급URL : https://stackoverflow.com/questions/25091130/django-migration-strategy-for-renaming-a-model-and-relationship-fields
'programing' 카테고리의 다른 글
여러 GROUP BY가 포함된 전체 요약 (0) | 2023.07.16 |
---|---|
유형 스크립트로 Angular2 버전을 확인하는 방법 (0) | 2023.07.16 |
장고 템플릿의 사전에서 사전을 통해 반복하는 방법은 무엇입니까? (0) | 2023.07.16 |
ggplot2를 사용하여 만든 그림의 배경색을 변경하는 방법 (0) | 2023.07.16 |
gitstash 실수: gitstash pop과 합병 충돌로 끝났습니다. (0) | 2023.07.16 |