백엔드 Back-end/장고 Django

Q. 장고Django에서 같은 이름으로 인덱스index를 추가할 수 있을까?

Tap to restart 2023. 2. 12. 21:00
반응형

A. 장고 2.2.x 버전에서는 추가할 수 있고, 장고 3.2.x 버전에서는 추가할 수 없다.


장고 버전 3.2.x에서 인덱스 name을 같은 이름으로 하면 유일한 이름이 아니라고 makemigrations에서 에러가 발생한다.

사례

예제 코드 DRF - CRUD를 활용해서 테스트 해보자.
테스트를 위해서 모델에 아래처럼 인덱스를 추가하자.

class Category(models.Model):
    name = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "category"
        indexes = [
            models.Index(fields=["name"], name="category_id"),
        ]


class Beverage(models.Model):
    name = models.CharField(max_length=200)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    price = models.IntegerField()
    is_available = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "beverage"
        indexes = [
            models.Index(fields=["category"], name="category_id"),
        ]

그러고나서 python manage.py makemigrations 명령어로 마이그레이션 파일을 생성하자.
그럼 바로 에러가 난다.
?: (models.E030) index name 'category_id' is not unique among models: app.Beverage, app.Category.

에러 발생 화면

 

해결 방법

name="category_id" 때문에 발생한 것이라 이 부분을 삭제하면 마이그레이션 파일이 잘 생성된다.
마이그레이션 파일을 열어보면 인덱스 이름이 자동으로 생성된 것을 볼 수 있다.

        migrations.AddIndex(
            model_name='category',
            index=models.Index(fields=['name'], name='category_name_d601b7_idx'),
        ),
        ...
        migrations.AddIndex(
            model_name='beverage',
            index=models.Index(fields=['category'], name='beverage_categor_68d5bd_idx'),
        ),
    ]

위 예처럼 이름이 예쁘게 되지 않고 자기 멋대로 된다. name을 중복 없이 선언하고 싶다면 규칙을 만들면 된다.
장고가 자동 생성하는 규칙처럼 테이블명_칼럼명_idx로 해도 되고, idx_테이블명_칼럼명, 테이블명_idx_칼럼명으로 할 수도 있다.
예를 들명 beverage_category_id_idx, idx_beverage_category_id, beverage_idx_category_id 로 할 수 있다. 이렇게 하면 중복 없이 선언 가능하다.

왜 중복으로 선언하면 안 될까

공식문서를 보면 데이터베이스에서 유일해야 한다는 조건을 발견할 수 있다.
"The CONSTRAINT symbol value, if defined, must be unique in the database. A duplicate symbol results in an error similar to: ERROR 1005 (HY000): Can't create table 'test.fk1' (errno: 121)."
출처: 13.1.20.5 FOREIGN KEY Constraints

정말 MySQL에 index 추가 시 이름이 같으면 안 될까?

그렇다고 MySQL에서 실제로 추가해 보면 중복이 있다고 추가가 안 되는 것은 아니다.
아래처럼 추가해보면

ALTER TABLE category
ADD INDEX category_id (name);

실제로 아래처럼 추가된 걸 볼 수 있다.

beverage 테이블에 이미 category_id 로 index가 추가된 상태인데도.

unique index라고 제한이 안 걸린 게 아니다. unique index로도 문제 없이 추가된다.

ALTER TABLE category
ADD UNIQUE INDEX category_id (name);

아래 보면 Non_unique가 0으로 unique index로 추가된 것을 볼 수 있다.

 

반응형