【Django】CharFieldのmaxlengthを変更する

django

Django の CharField の max_length (min_length) の設定値 fields や base_fields で参照することで変更できますが、バリデーションや HTML で出力したときの maxlength は init 時に設定されるため変更されません。

仕様によっては定義したあとに変更したいケースも存在するのでその方法について一例を紹介します。

実装

# fields.py
from django.forms.fields import CharField
class CustomCharField(CharField):
    def reset_max_length(self, max_length: int = None):
        prev = self.max_length
        self.max_length = max_length
        v = None
        if max_length:
            # パラメータの max_length が設定されている場合は、新しい validator を定義する
            v = validators.MaxLengthValidator(max_length)
        else:
            # 削除するため同じ validator を定義する
            v = validators.MaxLengthValidator(prev)
        self.reset_validator(validator, is_remove=not max_length)
        self.reset_widget_attrs("maxlength", value=max_length)
    
    def reset_validator(self, validator, is_remove: bool = False):
        """validatorを初期化"""
        exists = False
        index: int = None
        for i, v in enumerate(self.validators):
            # パラメータの validator と同じものの index をシュトック
            if isinistance(v, type(validator)):
                index = i
                break
        if index:
            # 同じ validator が存在する場合
            if is_remove:
                del self.validators[index]
            else:
                self.validators[index] = validator
        elif not is_remove:
            self.validators.append(validator)
    
    def reset_widget_attrs(self, key: str, value=None):
        """widgetの属性を初期化"""
        if key in self.widget.attrs:
            if value:
                self.widget.attrs[key] = value
            else:
                del self.wiget.attrs[key]

以下のように fields の設定を変更したい箇所で呼び出すような使い方を想定しています。

# forms.py
self.fields["text"].reset_max_length(max_length=200)
タイトルとURLをコピーしました