2016-06-21 3 views
0

임의의 문자열을 생성하는 (unique_id)라는 모델 필드가 있습니다. Posts 모델 호출에 정의됩니다.모델 필드 고유성 유효성 검사 오류 처리

unique_id = models.CharField(db_index=True, default=generate_id()) 

generate_id 기능은 고유 아니었다면

import random 
a = 'ABCDEFJHIJKLMNOPQRSTUVWXYZabcdefjhijklmnopqrstuvwxyz_-123456789'  

def generate_id(length=6): 
     return ''.join(random.choice(a) for i in range(length)) 

장고가 IntegrityError: UNIQUE constraint failed을 올릴 것입니다.

데이터베이스 수준에서 고유 IDS가 중복되는 것을 방지하는 올바른 방법은 무엇입니까?

+3

기본 속성에서 함수를 호출하면 안됩니다. 호출 가능 자체를 전달하십시오. –

+0

머리를 가져 주셔서 감사합니다. – static

답변

2

, default 값을 callable로 설정할 수 있습니다.이 값은 오브젝트가 생성 될 때마다 함수를 호출하기 때문에 더 좋지만, 필드 definit에서 호출하면 유용합니다 이 intepret 시간

unique_id = models.CharField(db_index=True, default=generate_id) 

에 한 번 호출됩니다에 두 번째로 내가 당신을 위해 임의의 문자열의 생성을 수행 인 UUIDField를 사용하는 것이 좋습니다 것입니다.

문제를 해결하려면 2 가지 방법이 있습니다. unique_id 꽤 길게 생성하십시오. 12 자 이상이어야합니다. 그러면 충돌이 거의 발생하지 않을 것입니다. 또는 당신은 당신의 generate_id 기능에 DB 검사를 추가 할 수 있습니다

def generate_id(length=6): 
    unique_id = ''.join(random.choice(a) for i in range(length)) 
    while Mymodel.objects.filter(unique_id=unique_id).exists(): 
     unique_id = ''.join(random.choice(a) for i in range(length)) 
    return unique_id 

방법 모델은

class Post(models.Model): 
    def _generate_id(self, length=6): 
     unique_id = ''.join(random.choice(a) for i in range(length)) 
     while self.__class__.objects.filter(unique_id=unique_id).exists(): 
      unique_id = ''.join(random.choice(a) for i in range(length)) 
     return unique_id 

아래의 예에서와 같이 self.__class__를 통해 액세스하지만 방법이 될 것입니다 경우 당신은하지 않습니다 수 있습니다 자동 응답 코멘트self 인스턴스가 없으므로 기본값으로 필드에 추가 할 수 있어야합니다. 하지만 @classmethod 데코레이터를 사용해보세요. 이것은 오브젝트를 인스턴스화하기 전에 _generate_id을 정의한 경우에만 가능하며 파이썬 클래스는 자신의 작은 네임 스페이스이기 때문에 @classmethods에서만 작동합니다.

class Post(models.Model): 
    @classmethod 
    def _generate_id(cls, length=6): 
     unique_id = ''.join(random.choice(a) for i in range(length)) 
     while cls.objects.filter(unique_id=unique_id).exists(): 
      unique_id = ''.join(random.choice(a) for i in range(length)) 
     return unique_id 

    unique_id = models.CharField(db_index=True, default=_generate_id, max_length=12) 

하지만 실생활에서 나는 결코 이것을 시도하지 않았습니다.

+0

해명 해 주셔서 감사합니다. 모델을 참조하는 방법이 있습니다 (포스트) 모델 자체에서? 'Post._generate_id' 메소드를 정의하려고 시도하고 있으므로 모델 내부에서 디폴트로 사용할 수 있습니다. – static

+0

@static 클래스 내부에는 generate_id를 사용할 수 없습니다. –

+1

업데이트 된 답변 읽기. 일반적으로 메소드와 같은 generate_id를 사용할 필요는 없지만,'@ classmethod' 데코레이터로 두 번째 예제가 필요하다면 –

0

모델 선언에 문제가 있으므로 기본값으로 generate_id()을 사용 했으므로 해당 호출의 출력이 기본값으로 사용됩니다.

아이디를 객체가 생성 될 때마다 생성이

unique_id = models.CharField(db_index=True, default=generate_id)

이 부를 것이다 사용해보십시오

참조 : @DanielRoseman이 default에서 함수를 호출하지 않는 것을 특징으로 첫째 https://docs.djangoproject.com/en/1.9/ref/models/fields/#default

+0

이것은 무작위로 중복 ID를 만드는 것을 어떻게 멈추게합니까? – Sayse

+0

, 그렇지 않으면 논리가 generate_id 함수에 맞게 수정되어야합니다. 위의 질문에 대해 똑같은 가치가 반복해서 주어집니다. generate_id가 10을 반환하면 파이썬 파일을 실행하는 동안 같이 저장되는 모든 객체는 동일한 특정 프로세스에 대해 값 10을 갖습니다.그래서 호출 가능 객체가 생성 될 때마다 함수가 호출되도록 보장합니다. –

관련 문제