13

LowerCaseCharField を実装しました。より良い実装の提案をいただければ幸いです。

from django.db.models.fields import CharField

class LowerCaseCharField(CharField):
    """
    Defines a charfield which automatically converts all inputs to
    lowercase and saves.
    """

    def pre_save(self, model_instance, add):
        """
        Converts the string to lowercase before saving.
        """
        current_value = getattr(model_instance, self.attname)
        setattr(model_instance, self.attname, current_value.lower())
        return getattr(model_instance, self.attname)

実際、私たちは次のものを持っているのが大好きです:

> modelinstance.field_name="TEST"
> print modelinstance.field_name
'test'

現在の実装では、保存時にのみ小文字に変換されます。

4

4 に答える 4

19

をオーバーライドto_pythonすると、データベース検索時に小文字以外の文字列を比較できるようになります。実際のメソッドは ですがget_prep_value、それは を呼び出すto_pythonためCharField、それをオーバーライドする方が便利です。

def to_python(self, value):
    value = super(LowerCaseCharField, self).to_python(value)
    if isinstance(value, basestring):
        return value.lower()
    return value

これで、次のようなクエリを実行できます。

MyModel.objects.filter(lccf="MiXeD")

編集:

質問を読み直すと、引き下げをすぐに有効にしたいようです。__get__これを行うには、記述子 (および__set__メソッドを備えた新しいスタイルの python オブジェクト、関連モデルの python ドキュメントと django コードを参照) を作成し、フィールドをオーバーライドcontribute_to_classして、モデルのフィールドを記述子に設定する必要があります。

これは、設定の値を変更したいすべてのフィールドで再利用できるはずです。

class ModifyingFieldDescriptor(object):
    """ Modifies a field when set using the field's (overriden) .to_python() method. """
    def __init__(self, field):  
        self.field = field  
    def __get__(self, instance, owner=None):
        if instance is None:
            raise AttributeError('Can only be accessed via an instance.')  
        return instance.__dict__[self.field.name]
    def __set__(self, instance, value):
        instance.__dict__[self.field.name] = self.field.to_python(value)

class LowerCaseCharField(CharField):
    def to_python(self, value):
        value = super(LowerCaseCharField, self).to_python(value)
        if isinstance(value, basestring):
            return value.lower()
        return value
    def contribute_to_class(self, cls, name):
        super(LowerCaseCharField, self).contribute_to_class(cls, name)
        setattr(cls, self.name, ModifyingFieldDescriptor(self))
于 2010-02-28T10:17:00.570 に答える
1

django.models.Models はクラス属性に基づいてインスタンス属性を魔法のように設定するため、Python プロパティの使用は簡単ではありません。これには未解決のバグがあります。

元のポスターが行ったことを正確に行うことになりました。

それはあなたがしなければならないことを意味します:

>>> modelinstance.field_name="TEST"
>>> modelinstance.save() # Extra step
>>> print modelinstance.field_name
'test'
于 2010-03-01T13:28:41.523 に答える
0

field_name をプロパティにしてみて、ゲッターまたはセッターで何でもします。

于 2010-02-28T10:16:13.540 に答える