Django 앱의 이름을 바꾸는 방법



처음에 1st things 1st에 대한 MVP(최소 실행 가능한 제품)를 만들었을 때 전체 Django 프로젝트가 우선순위에 관한 것이라고 생각했습니다. 몇 년 후 저는 Django 프로젝트가 SaaS(Software as a Service)에 관한 것이며 우선 순위 지정은 SaaS가 작동하는 데 필요한 모든 기능의 일부일 뿐이라는 것을 깨달았습니다. 깨끗하고 잘 정리된 코드를 갖도록 앱 이름을 바꿔야 했습니다. 내가 한 방법은 다음과 같습니다.

0. 코드와 데이터베이스를 최신 상태로 유지



최신 git pull이 있는지 확인하고 모든 데이터베이스 마이그레이션을 실행하십시오.

1. django-rename-app 설치


django-rename-app를 pip 요구 사항에 넣고 설치하거나 다음을 실행하십시오.

(venv)$ pip install django-rename-app


설정에서 앱을 INSTALLED_APPS에 넣습니다.

INSTALLED_APPS = [
    # …
    "django_rename_app",
]


2. 앱 디렉토리 이름 바꾸기



앱 및 템플릿에서 oldapp의 이름을 newapp로 바꿉니다.

3. 코드에서 발생하는 앱 이름의 이름을 바꿉니다.



모든 가져오기, 관계, 마이그레이션 및 템플릿 경로에서 앱의 이름을 바꿉니다.
oldapp 에 대한 전체 검색을 수행한 다음 해당 용어의 이름을 newapp 로 변경해야 하는 경우와 그렇지 않은 경우를 사례별로 확인할 수 있습니다.

4. 관리 명령 rename_app 실행



관리 명령 실행rename_app:

(env)$ python manage.py rename_app oldapp newapp


이 명령은 앱 접두어의 이름을 앱 테이블과 django_content_typedjango_migrations 테이블의 레코드로 바꿉니다.

스테이징 또는 프로덕션 서버를 업데이트하려는 경우 배포 스크립트(Ansible, Docker 등)에서 마이그레이션을 실행하기 전에 rename_app 명령을 추가하십시오.

5. 인덱스 및 제약 조건 업데이트



마지막으로 인덱스 및 외래 키 제약 조건을 업데이트하는 사용자 지정 코드를 사용하여 앱에 대한 빈 데이터베이스 마이그레이션을 생성합니다.

(env)$ python manage.py makemigrations newapp --empty --name rename_indexes


다음 코드로 마이그레이션을 채웁니다.

# newapp/migrations/0002_rename_indexes.py
from django.db import migrations


def named_tuple_fetch_all(cursor):
    "Return all rows from a cursor as a namedtuple"
    from collections import namedtuple

    desc = cursor.description
    Result = namedtuple("Result", [col[0] for col in desc])
    return [Result(*row) for row in cursor.fetchall()]


def rename_indexes(apps, schema_editor):
    from django.db import connection

    with connection.cursor() as cursor:
        cursor.execute(
            """SELECT indexname FROM pg_indexes 
            WHERE tablename LIKE 'newapp%'"""
        )
        for result in named_tuple_fetch_all(cursor):
            old_index_name = result.indexname
            new_index_name = old_index_name.replace(
                "oldapp_", "newapp_", 1
            )
            cursor.execute(
                f"""ALTER INDEX IF EXISTS {old_index_name} 
                RENAME TO {new_index_name}"""
            )


def rename_foreignkeys(apps, schema_editor):
    from django.db import connection

    with connection.cursor() as cursor:
        cursor.execute(
            """SELECT table_name, constraint_name 
            FROM information_schema.key_column_usage
            WHERE constraint_catalog=CURRENT_CATALOG 
            AND table_name LIKE 'newapp%'
            AND position_in_unique_constraint notnull"""
        )
        for result in named_tuple_fetch_all(cursor):
            table_name = result.table_name
            old_foreignkey_name = result.constraint_name
            new_foreignkey_name = old_foreignkey_name.replace(
                "oldapp_", "newapp_", 1
            )
            cursor.execute(
                f"""ALTER TABLE {table_name} 
                RENAME CONSTRAINT {old_foreignkey_name} 
                TO {new_foreignkey_name}"""
            )


class Migration(migrations.Migration):

    dependencies = [
        ("newapp", "0001_initial"),
    ]

    operations = [
        migrations.RunPython(rename_indexes, migrations.RunPython.noop),
        migrations.RunPython(rename_foreignkeys, migrations.RunPython.noop),
    ]


마이그레이션을 실행합니다.

(env)$ python manage.py migrate


원하는 대로 작동하지 않는 경우 다시 이전하고 코드를 수정한 다음 다시 이전합니다. 다음과 같이 마지막 마이그레이션 이전 단계로 마이그레이션하여 마이그레이션을 취소할 수 있습니다.

(env)$ python manage.py migrate 0001


6. 정리



필요한 모든 환경에서 마이그레이션을 적용한 후 pip 요구 사항 및 배포 스크립트에서 django-rename-app를 제거하여 정리할 수 있습니다.

최종 단어



처음부터 모든 요구 사항을 충족하는 시스템을 구축하는 것은 거의 불가능합니다. 적절한 시스템에는 항상 지속적인 개선과 리팩토링이 필요합니다. Django 마이그레이션과 django-rename-app 의 조합을 사용하면 민첩하고 깔끔하며 유연한 방식으로 웹 사이트에서 작업할 수 있습니다.

즐거운 코딩하세요!


표지 사진 by freestocks .

좋은 웹페이지 즐겨찾기