Today
-
Total
-
  • [django] Model IntegerField에 최소/최대값 지정하기
    Coding/Python 2021. 1. 19. 18:49

    안녕하세요. 오늘은 장고의 Model을 사용하면서 정수를 입력받는 IntegerField에서 최소/최댓값을 지정하는 방법에 대해 포스팅합니다.

     

     

     👀 배경

    저는 장고의 기본 어드민을 그대로 사용하고 있기 때문에, validation 처리를 하면서 장고의 기능을 전적으로 활용하는 수 밖에 없었습니다. 그러던 와중 정수의 최소, 최댓값을 0~5로 지정해야 하는 이슈가 발생했습니다. help_text를 이용하면 사용하는 유저에게 0~5 사이 값을 입력해야 한다고 권고할 수는 있지만, 확실한 validation 처리는 불가능했습니다.

     

    class Post(models.Model):
        num = models.IntegerField("숫자", default = 0, help_text="0~5사이 값으로 입력하세요")

     

    저만 사용하면 조심해서 사용하면 되겠지만, 여러 명이 사용하는 관리자 페이지 특성 상 5보다 큰 숫자가 들어가게 되면 로직에 문제가 발생하기 때문에 저는 무조건 값 범위를 강제하기 위해 여러 방법들을 찾아보았습니다.

     

     


     

    IntegerField를 상속받는 새 Model 만들기

     

    from django.db import models
    
    class IntegerRangeField(models.IntegerField):
        def __init__(self, verbose_name=None, name=None, min_value=None, max_value=None, **kwargs):
            self.min_value, self.max_value = min_value, max_value
            models.IntegerField.__init__(self, verbose_name, name, **kwargs)
        def formfield(self, **kwargs):
            defaults = {'min_value': self.min_value, 'max_value':self.max_value}
            defaults.update(kwargs)
        
        return super(IntegerRangeField, self).formfield(**defaults)

     

    보통 장고 Model에서 기본으로 제공하는 IntegerField를 사용하여 정수를 입력받지만, 이를 상속받는 새로운 클래스를 만드는 방법도 존재했습니다. 이는 IntegerField와 흡사하나 클래스 변수로 min_value와 max_value를 입력받아 객체에 전달하는 방식입니다. 이럴 경우 IntegerField와 유사한 기능과 동작하면서도 최소, 최대값이 존재하는 모델이 됩니다.

     

    이 방법을 통해 최소, 최댓값을 제한할 수 있다는 점은 증명되었으나 사용법이 다소 난해하다는 생각이 들었습니다. 그러던 와중 장고의 기본 기능으로 validator를 제공한다는 사실을 알게되었습니다.

     

     


     

    Choices를 활용하여 선택 강제하기

     

    num_choices = zip( range(1,n), range(1,n) )
    num = models.IntegerField(choices=num_choices, blank=True)

     

    파이썬의 range 함수는 범위를 반환해주는 함수이기 때문에 이를 활용하면 choices를 활용하여 선택의 폭을 제한할 수 있습니다. 원래는 성별을 '남', '녀'중에 선택하여야 하는 경우 등에 대하여 CharField에 자주 사용하는 choices이지만 다음과 같이 IntegerField에도 사용은 할 수 있습니다. 다만 choices를 넣으면 드롭다운 형식으로 출력되는 특성상 숫자 범위가 너무 커지면 선택하기가 힘들어질 수는 있겠습니다.

     


     

    Django validator 사용하기

     

    from django.db import models
    from django.core.validators import MinValueValidator, MaxValueValidator
    
    num = models.IntegerField(validators=[MinValueValidator(0),
                                           MaxValueValidator(5)])

     

    역시나 장고는 기본적으로 validator를 제공하고 있었습니다. import만 해주고 사용하면 바로 제한이 가능했습니다. 이를 활용하면 단순히 숫자 범위 제한 뿐만 아니라 핸드폰번호, url 등등의 validation 처리가 가능했습니다. 단 이 경우 validator가 기본으로 제공되는 Field에 한하여 적용되기 때문에 IntegerField가 아닌 자체 제작(IntegerField를 상속받지 않은)한 Field에 사용할 경우 에러가 발생합니다.

    장고가 내장하고 있는 기능이기 때문에 개인적으로 저는 이 방법이 가장 좋다고 느껴져 채택하기로 했습니다.

     

     

    📚 출처

    stackoverflow.com/questions/849142/how-to-limit-the-maximum-value-of-a-numeric-field-in-a-django-model

    - 스택오버플로우(장고의 숫자 필드 값을 제한하는 법)

    댓글