2009-09-07 1 views
5

객체가 고유한지 확인하고 싶지 않은 경우 사용자가 객체를 저장하려고 할 때 오류가 발생하기를 원합니다 (예 : 관리자를 통해). 고유 한 의미는 객체의 속성 중 일부가 다른 객체의 속성과 동일한 값을 가질 수도 있지만 모든 객체가 다른 객체의 값과 동일하지는 않습니다. 내가 잘못 본게 아니라면Django의 고유 한 객체 DRY

, 난과 같이이 작업을 수행 할 수 있습니다

class Animal(models.Model): 
    common_name = models.CharField(max_length=150) 
    latin_name = models.CharField(max_length=150) 
    class Meta: 
     unique_together = ("common_name", "latin_name") 

를하지만 그때마다 나는 모델을 리팩토링 (예 : 새 필드를 추가하거나 기존 필드의 이름을 변경), unique_together에 할당 된 괄호 안의 필드 목록을 편집해야합니다. 단순한 모델을 사용하면 괜찮습니다. 그러나 실제로는 리팩토링하는 동안 번거로운 작업이됩니다.

unique_together 괄호 안에 필드 이름 목록을 반복해서 입력하지 않아도되는 것을 어떻게 피할 수 있습니까? 모델 필드의 목록을 변수에 전달하고 그 변수를 unique_together 대신 할당 할 수있는 방법이 있습니까?

+1

+1 (또는 추상 기본 클래스가 Model을 확장하고 메타 클래스를 오버라이드 (override) 파생) - 위대한 문제. 나는 할 수 있다고 생각하지 않지만 다른 사람들의 의견을 듣고 싶어합니다. –

+0

+1 - 누군가가 좋은 해결책을 찾을 수 있다면 정말 재미 있습니다. 나는 시도했지만 반사를 통해 작동하지 못했습니다. 왜냐하면 Animal 클래스에서 속성을 읽을 수 없기 때문입니다 (Animal이 완전히 정의되지 않았기 때문에 분명합니다). – FlorianH

+0

jtiai on irc : //irc.freenode.net/django는 질문을 토론하기 위해 시간을내어 "내 자신의"AllUniqueModel "클래스를 추가하고 표준"Model "을 상속하고 모든 필드를 주입하는 데 필요한 일부 메타 클래스 마법을 만들 수 있다고 제안했습니다. unique_togerther 표준 생성 절차에 따라 처리됩니다. ' jtiai가 무엇을 의미하는지 완전히 모르겠지만, 나는 기대했던 것보다 더 복잡한 해결책처럼 들립니다. – sampablokuper

답변

4

리팩토링 모델은 할 수있는 다소 비싼 것입니다 :

  • 필드 이름 속성을 객체에 해당하기 때문에 당신은 당신의 모델을 사용하는 모든 코드를 변경해야합니다
  • 당신은 장고 때문에 데이터베이스를 수동으로 변경해야합니다 당신을 위해 이것을 할 수 없다 (적어도 내가 장고로 작업했을 때 마지막으로 사용한 버전)

따라서 모델 메타 클래스의 고유 한 필드 이름 목록을 업데이트하는 것이 걱정해야한다. 합.

편집 : 당신이 정말로 "함께 독특한"해야합니다 당신의 모든 필드을이 작업을 수행 할 수 및 경우는 Freenode에있는 사람이 바로이며, 사용자 정의 메타 클래스를 작성해야합니다. 이것은 매우 복잡하고 에러 프라 인입니다. 그리고 코드가 장고의 향후 릴리스와 호환되지 않을 수도 있습니다.

장고의 ORM "마법"은 일반 기본 클래스 Model의 메타 클래스 ModelBase (django.db.models.base.ModelBase)에 의해 제어됩니다. 이 클래스는 모든 필드와 메타 정보로 클래스 정의를 가져와 나중에 코드에서 사용할 클래스를 구성합니다. 자신의 메타 클래스를 사용하는

  1. 서브 클래스 ModelBase : 여기

    당신이 당신의 목표를 달성 할 수있는 방법에 대한 조리법이다.
  2. 재정의 방법 __new__(cls, name, bases, dict)
  3. Meta 회원 (dict["Meta"])뿐만 아니라 당신이 수집 한 필드의 이름을 기반으로하는 모든 필드 회원
  4. 설정 meta.unique_together를 수집하기 위해 dict을 검사합니다.
  5. 전화 슈퍼 구현 (ModelBase.__new__)
  6. 사용 마법의 멤버 __metaclass__ = MyMetaclass을 사용하여 모든 사용자의 고유 모델의 사용자 정의 메타 클래스
+1

프로토 타이핑 단계에서 리팩토링 모델은 저렴하지만 코드 복제가 비용이 많이 들기 때문에 제 질문이 있습니다. 분명히 제작 과정에서 문제는 다르지만 내 질문에 대한 좋은 대답을 찾을 수 있다면 적어도 제작시 리팩터링 할 때 취해야 할 단계의 * 1 *을 줄일 수 있습니다. – sampablokuper

+1

긴 답변에 대한 업데이트 된 응답을 참조하십시오. 아마도 너무 복잡 할 수도 있습니다. –

+2

응답을 보내 주셔서 감사합니다. 그렇습니다, 이것을 성취하는 것은 상당히 번거로운 일입니다. 흠. Django가 ** unique \ _together = (all) ** 또는 somesuch를 지정하는 옵션을 제공 할 수 있거나 메타 옵션으로 전달하기위한 필드 목록을 생성하기 위해 모델에서 자체 검사를 수행하도록 허용 할 수 있다면 매우 좋을 것입니다. . 아니면 둘다 :) – sampablokuper