web-dev-qa-db-ja.com

Djangoモデルの数値フィールドの最大値を制限する方法は?

Djangoには、モデルで使用できるさまざまな数値フィールドがあります。 DecimalField および PositiveIntegerField 。前者は、格納される小数点以下の桁数と格納される文字の全体数に制限できますが、特定の範囲内のonly数値の格納に制限する方法はありますか? 0.0-5.0?

それに失敗した場合、PositiveIntegerFieldを、たとえば50までの数値のみを格納するように制限する方法はありますか?

更新:Bug 6845 終了しました で、このStackOverflowの質問は無意味かもしれません。 -sampablokuper

138
sampablokuper

カスタムモデルフィールドタイプを作成することもできます- http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields を参照してください

この場合、組み込みのIntegerFieldから「継承」して、検証ロジックをオーバーライドできます。

これについて考えれば考えるほど、これが多くのDjangoアプリにどれほど役立つかがわかります。おそらく、IntegerRangeField型をDjango devsのパッチとして送信して、トランクへの追加を検討することができます。

これは私のために働いています:

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)

次に、モデルクラスで次のように使用します(フィールドは上記のコードを配置するモジュールです)。

size = fields.IntegerRangeField(min_value=1, max_value=50)

負と正の範囲のOR(発振器の範囲など):

size = fields.IntegerRangeField(min_value=-100, max_value=100)

本当にクールなのは、次のような範囲演算子を使用して呼び出すことができる場合です:

size = fields.IntegerRangeField(range(1, 50))

ただし、「skip」パラメーターを指定できるため、より多くのコードが必要になります-range(1、50、2)-興味深いアイデア...

125
NathanD

Djangoの組み込みバリデーター —を使用できます

from Django.db.models import IntegerField, Model
from Django.core.validators import MaxValueValidator, MinValueValidator

class CoolModelBro(Model):
    limited_integer_field = IntegerField(
        default=1,
        validators=[
            MaxValueValidator(100),
            MinValueValidator(1)
        ]
     )

Edit:これらは ModelFormでモデルを使用している場合にのみ機能します ですが、モデルを使用している場合は機能しません「独力で」ため息。

278
user1569050
from Django.db import models
from Django.core.validators import MinValueValidator, MaxValueValidator

size = models.IntegerField(validators=[MinValueValidator(0),
                                       MaxValueValidator(5)])
69
congocongo

私はこれとまったく同じ問題を抱えていました。ここに私の解決策がありました:

SCORE_CHOICES = Zip( range(1,n), range(1,n) )
score = models.IntegerField(choices=SCORE_CHOICES, blank=True)
50
chris.haueter

これを行うには2つの方法があります。 1つは、フォーム検証を使用して、ユーザーが50を超える数値を入力しないようにすることです。 フォーム検証ドキュメント

プロセスにユーザーが関与していない場合、またはフォームを使用してデータを入力していない場合は、モデルのsaveメソッドをオーバーライドして、例外をスローするか、フィールドに入るデータを制限する必要があります。

10
tghw

柔軟性を高め、モデルフィールドを変更したくない場合に最適なソリューションを次に示します。このカスタムバリデータを追加するだけです。

#Imports
from Django.core.exceptions import ValidationError      

class validate_range_or_null(object):
    compare = lambda self, a, b, c: a > c or a < b
    clean = lambda self, x: x
    message = ('Ensure this value is between %(limit_min)s and %(limit_max)s (it is %(show_value)s).')
    code = 'limit_value'

    def __init__(self, limit_min, limit_max):
        self.limit_min = limit_min
        self.limit_max = limit_max

    def __call__(self, value):
        cleaned = self.clean(value)
        params = {'limit_min': self.limit_min, 'limit_max': self.limit_max, 'show_value': cleaned}
        if value:  # make it optional, remove it to make required, or make required on the model
            if self.compare(cleaned, self.limit_min, self.limit_max):
                raise ValidationError(self.message, code=self.code, params=params)

そして、次のように使用できます。

class YourModel(models.Model):

    ....
    no_dependents = models.PositiveSmallIntegerField("How many dependants?", blank=True, null=True, default=0, validators=[validate_range_or_null(1,100)])

2つのパラメーターはmaxとminで、nullを許可します。必要に応じて、マークされたifステートメントを削除するか、モデルでフィールドを空白= False、null = Falseに変更することで、バリデーターをカスタマイズできます。もちろん、移行が必要になります。

注:DjangoはPositiveSmallIntegerFieldの範囲を検証せず、代わりにこのフィールドのsmallint(postgres内)を作成し、指定された数値が範囲外の場合はDBエラーが発生するため、バリデーターを追加する必要がありました。

これがお役に立てば幸いです:) Djangoのバリデーター

PS。私の答えはDjango.core.validatorsのBaseValidatorに基づいていますが、コード以外はすべて異なります。

5
radtek