django "어떻게"시리즈 3: 모델 필드를 작성하는 방법(model filed)

12635 단어 django
django는 자체적으로 많은 필드 클래스인 CharField,DateField 등을 가지고 있습니다. 만약에 django의 이 필드들이 당신의 정확한 요구를 충족시키지 못한다면 당신은 자신의 모델 필드를 작성할 수 있습니다.
django가 자체로 가지고 있는 필드는 데이터베이스 열 유형과 일일이 대응하지 않고 간단한VARCHAR,INTEGER 등 유형만 있습니다. 더 복잡한 유형, 예를 들어 다각형을 사용하기 위해 필드를 정의할 수 있습니다.또는, 당신은 매우 복잡한 대상이 있을 수 있습니다. 이 대상은 어떤 방법을 통해 표준화된 데이터베이스 열 유형을 서열화할 수 있으며, 그러면 당신은 자신의 역자류를 정의할 수 있습니다.
예제 객체
사용자 정의 영역을 만들려면 특별한 문제에 주의해야 합니다. 문제를 더욱 간단하게 설명하기 위해서, 우리는 하나의 예를 사용해서 설명합니다.
우리는 포커 한 벌을 예로 사용하는데, 종류Hand는 한 개의 카드를 대표하고, 한 개의 카드는 52장이 있는데, 평균적으로 네 명의 유저에게 동서남북으로 보낸다
class Hand(object):

    """A hand of cards (bridge style)"""



    def __init__(self, north, east, south, west):

        # Input parameters are lists of cards ('Ah', '9s', etc)

        self.north = north

        self.east = east

        self.south = south

        self.west = west



    # ... (other possibly useful methods omitted) ...

 
이것은 정상적인python 클래스일 뿐입니다. 어떤django 특성도 없습니다. 우리는hand속성이 우리의 모델에서hand실체라고 가정하면 다음과 같은 일을 할 수 있습니다.
example = MyModel.objects.get(pk=1)

print example.hand.north



new_hand = Hand(north, east, south, west)

example.hand = new_hand

example.save()

 
우리는 모델에서 값을 부여하고 Hand 속성을 검색합니다. 이것은 다른python 클래스와 다를 것이 없습니다. 문제는django가 이러한 대상을 저장하고 불러오는 것을 어떻게 처리하는가입니다.
배경 이론
데이터베이스 저장소
모델의 영역은 어쨌든 이미 존재하는 데이터베이스 열 형식 중 적합한 것으로 변환되어야 한다.비록 서로 다른 데이터베이스가 서로 다른 열 유형의 집합을 제공하지만, 규칙은 모두 같다. 당신이 무엇을 저장하든지, 제공하는 열 형식만 사용할 수 있다.따라서 데이터베이스 열 형식에 영합하거나 직접적인 방법으로 데이터를 문자열로 변환할 수 있다.
우리의 Hand 예에 따르면 우리는 포커 데이터를 104 문자열로 변환할 수 있다(예를 들어 북동남서 등). 그래서 Hand 대상은 텍스트나 문자의 형식으로 데이터베이스에 저장할 수 있다.
하나의 역류는 무엇을 하는가
우리가 이 절에서 말한 역류는 특별한 설명이 없으면 모두 모델역을 가리키며 표역이 아니다.
django의 모든 영역은django입니다.db.models.Field의 하위 클래스입니다.django의 클래스가 당신의 모델의 속성에 저장되지 않는다는 것을 깨닫는 것은 매우 중요하다. 모델 속성은 정상적인python 대상을 포함한다. 하나의 모델이 만들어질 때 당신이 하나의 모델에 정의한 클래스는meta클래스에 저장된다. 이것은 당신이 속성을 만들고 수정할 때만 클래스가 필요하지 않기 때문이다. 반대로역류는 속성 값과 데이터베이스 저장이나 서열화에 필요한 변환 메커니즘을 제공할 뿐이다.
자신의 영역을 만들 때, 위의 점을 기억하십시오.도메인을 사용자 정의해야 할 때 다음 두 가지 클래스만 만들 수 있다는 것을 기억하십시오.
  • 첫 번째 클래스는 사용자가 조종할 수 있는python 대상
  • 두 번째 클래스는 Field의 하위 클래스
  • 입니다.
    다음은 저희가 예를 들어 말씀드릴게요.
    필드 하위 클래스 만들기
    당신의 filed 하위 클래스를 디자인할 때 가장 먼저 고려해야 할 것은 그 신발에 이미 존재하는 클래스가 당신의 요구에 비교적 가깝다는 것입니다. 만약에 있다면 그 클래스를 계승하세요. 그렇지 않으면 Field라는 비교적 밑바닥의 클래스를 계승할 수 밖에 없습니다.
    당신의 클래스를 초기화하는 것은 사실 하나입니다. 당신이 보낸 구체적인 파라미터를 분리해서 Filed (또는 어떤 부류) 에 전달하는init__() 방법
    우리의 예에서 우리는 우리의 영역을 HandField라고 부른다. 다른 영역류가 우리의 요구에 접근하지 않기 때문에 우리는 직접 Field를 계승하면 된다.
    from django.db import models
    
    
    
    class HandField(models.Field):
    
    
    
        description = "A hand of cards (bridge style)"
    
    
    
        def __init__(self, *args, **kwargs):
    
            kwargs['max_length'] = 104
    
            super(HandField, self).__init__(*args, **kwargs)

     
    이 예에서 우리의HandField는 대부분의 영역의 선택할 수 있는 매개 변수를 받아들인다. 다음은 우리가 소개할 것이다. 또한 우리는 그것이 정확한 길이max 를 확보했다.length,Field.__inti__()가 적용한 매개변수는 다음과 같습니다.
  • verbose_name
  • name
  • primary_key
  • max_length
  • unique
  • blank
  • null
  • db_index
  • rel: 관련 도메인에 사용되며 ForeignKey를 원합니다.고급 전용
  • default
  • editable
  • serialize: 기본값은 진짜입니다.False라면 이 필드가 시퀀스에 전달될 때 서열화되지 않습니다
  • unique_for_date
  • unique_for_month
  • unique_for_year
  • choices
  • help_text
  • db_column
  • db_tablespace: 인덱스만 만들 수 있습니다. 백엔드에서 tablespaces를 지원한다면 이 인자를 무시할 수 있습니다.
  • auto_created: 고급 전용
  • 특별히 설명하지 않았습니다. 이 매개 변수의 의미는django의 기본적인 의미와 일치합니다
    SubfieldBase 메타클래스
    두 가지 이유로 우리는 영역의 하위 클래스를 사용합니다. 일반적인 데이터베이스 열 형식을 이용하거나 복잡한python 형식을 처리합니다.분명히 둘을 하나로 합치는 것은 가능하다. 일반적인 상황에서는 네가 쓸 수 없다.
    만약 사용자 정의python 형식, 예를 들어 우리의Hand 클래스를 처리한다면,django가 우리 모델의 실례를 초기화하고 사용자 정의된 필드 속성에 데이터베이스 값을 부여할 때, 우리는 이 값을 적합한python 대상으로 변환할 수 있도록 확보해야 한다.이 과정 내부의 실현은 좀 복잡하지만, 우리가 써야 할 코드는 비교적 간단하다. 특정한 원류를 사용했는지 확인하는 것이다.다음과 같습니다.
    lass HandField(models.Field):
    
    
    
        description = "A hand of cards (bridge style)"
    
    
    
        __metaclass__ = models.SubfieldBase
    
    
    
        def __init__(self, *args, **kwargs):
    
            # ...

     
    이것은 속성이 초기화될 때 topython () 방법이 호출될 것입니다
    ModelForms 및 사용자 정의 도메인
    만약 당신이 Subfield Base를 사용한다면, topython () 은 필드의 실례가 할당될 때마다 호출됩니다. 이것은 할당이 언제 발생하든지 정확한 데이터 형식이나 비정상적인 처리가 있어야 한다는 것을 의미합니다.
    ModelForms를 사용할 때 이 점이 특히 중요합니다. ModelForm을 저장할 때,django는 폼 값을 사용하여 모델의 실례를 실례화합니다.그러나 정리된 폼 데이터가 유효한 입력이 되지 않으면 정상적인 폼 검증 과정이 중단됩니다.
    따라서 사용자 정의 필드를 표시하는 폼 필드를 확보해야 합니다. 입력 검증을 실행하든 데이터 정리를 하든 사용자가 제공한 폼 입력을 to 로 전환해야 합니다.python () 호환 가능한 모델 필드 값입니다.이것은 사용자 정의 폼 필드를 작성하거나 필드에서formfield () 방법을 실행하여 표현역 클래스를 되돌려 달라고 요구할 수 있습니다. 이 클래스의 topython () 이 정확한 데이터 형식을 되돌려줍니다.
    문서 사용자 정의 영역
    field.description
    예전과 같이, 사용자가 이것이 무엇인지 알 수 있도록 도메인 형식을 위한 문서를 작성해야 한다.필드를 사용합니다.이 주석은admindocs에서 사용할 수 있습니다.
    유용한 방법
    Field 하위 클래스를 만들고 설정하면metaclass__,너는 몇 가지 표준을 덮어쓰는 방법을 고려할 수 있다. 아래의 방법은 중요성에 따라 순서를 정한다
  • Field.db_type(self,connection):connection 대상과 관련 설정을 고려하여Field의 데이터베이스 열 데이터 형식을 되돌려줍니다.예를 들어 PostgreSQL 사용자 정의 형식 my type을 만들었습니다. Field를 계승한 다음db 를 실현할 수 있습니다.type() 방법은 다음과 같은 유형을 사용합니다.
    from django.db import models
    
    
    
    class MytypeField(models.Field):
    
        def db_type(self, connection):
    
            return 'mytype'

    MytypeField가 생기면 어떤 모델에서든 사용할 수 있습니다
    class Person(models.Model):
    
        name = models.CharField(max_length=80)
    
        something_else = MytypeField()

     

  • 만약 데이터베이스와 무관한 응용 프로그램을 만드는 데 주력한다면, 데이터베이스 열 형식에 따라 다른 점을 주의해야 한다. 예를 들어, 날짜 형식은 PostgreSQL에서timestamp이고, MySQL에서datetime라고 부른다. 그러면 이렇게 쓸 수 있다.
    class MyDateField(models.Field): def db_type(self,connection): #connection을 확인합니다.settings_dict['ENGINE'] 속성if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql': return 'datetime' else: return 'timestamp'
     
    db_type () 방법은 처음 테이블을 만들 때만django에서 호출되며, 다른 어느 때에도 호출되지 않기 때문에, 예를 들어connection을 검사하는 등 상당히 복잡한 코드를 실행할 수 있습니다.settings_dict['ENGINE'].
    일부 데이터베이스 열 속성은 매개 변수를 받아들인다. 예를 들어CHAR(25), 25는 최대 열 길이를 나타낸다. 여기서 너는 이렇게 쓸 수 있다. 비록 약간 어색하고 억지스럽지만.
    # This is a silly example of hard-coded parameters.
    
    class CharMaxlength25Field(models.Field):
    
        def db_type(self, connection):
    
            return 'char(25)'
    
    
    
    # In the model:
    
    class MyModel(models.Model):
    
        # ...
    
        my_field = CharMaxlength25Field()

     
    더 좋은 방법은 동적 전달 매개 변수입니다. 당신은 을 실현할 수 있습니다.init__() 동적 전달 매개 변수의 효과에 도달하기
     #       
    
    class BetterCharField(models.Field):
    
        def __init__(self, max_length, *args, **kwargs):
    
            self.max_length = max_length
    
            super(BetterCharField, self).__init__(*args, **kwargs)
    
    
    
        def db_type(self, connection):
    
            return 'char(%s)' % self.max_length
    
    
    
    # In the model:
    
    class MyModel(models.Model):
    
        # ...
    
        my_field = BetterCharField(25) 

    마지막으로, 당신의 열에 상당히 복잡한 SQL 설정이 필요하다면dbtype () 이 None을 되돌려줍니다. 이것은django의 SQL 생성 코드를 이 필드를 건너뛰게 합니다. 다른 방법으로 시계에 이 열을 만들어야 합니다.
  • Field.to_python(self,value): 데이터베이스나 시퀀스에서 되돌아오는 값을python 대상으로 변환합니다.기본 구현은 데이터베이스 백엔드가 정확한python 형식으로 값을 되돌려주기 때문에 간단하게 값을 되돌려줍니다.따라서 만약 귀환값이python의 기본 데이터 형식보다 더 복잡하다면, 이 방법을 덮어써야 한다. 일반적인 규칙에 따르면, 이 방법은 우아하게 처리해야 할 매개 변수:
  • 정확한 유형의 실례
  • 문자열 하나
  • 데이터베이스에서 당신이 사용하고 있는 모든 열 형식을 되돌려줍니다
    import re
    
    
    
    class HandField(models.Field):
    
        def to_python(self, value):
    
            if isinstance(value, Hand):
    
                return value
    
    
    
            # The string case.
    
            p1 = re.compile('.{26}')
    
            p2 = re.compile('..')
    
            args = [p2.findall(x) for x in p1.findall(value)]
    
            return Hand(*args)


  • Field.get_prep_value(self,value):topython () 은 반대로 (데이터베이스 백엔드와 협조할 때).

  • 좋은 웹페이지 즐겨찾기