Django LowerCaseCharField - PullRequest
       7

Django LowerCaseCharField

12 голосов
/ 28 февраля 2010

Мы реализовали 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 ]

16 голосов
/ 28 февраля 2010

Вы можете переопределить 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")

Редактировать:

Перечитывая ваш вопрос, похоже, вы хотите, чтобы понижение вступило в силу немедленно. Для этого вам нужно создать дескриптор (объект python нового стиля с методами __get__ и __set__, см. документы по питону и код 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))
1 голос
/ 01 марта 2010

Использование свойств Python непросто из-за того, как django.models.Models волшебным образом устанавливают свои атрибуты экземпляра на основе атрибутов класса. Для этого есть открытая ошибка .

В итоге я сделал именно то, что сделал оригинальный плакат.

Это означает, что вы должны сделать:

>>> modelinstance.field_name="TEST"
>>> modelinstance.save() # Extra step
>>> print modelinstance.field_name
'test'
0 голосов
/ 10 июля 2015

Еще один способ сделать это - добавить хук pre_save к вашей модели, а затем просто преобразовать все поля, которые вы хотите сделать строчными, в строчные, используя lower (). Это обсуждается здесь немного по-другому. Таким образом, каждый раз, когда объект сохраняется, его поле преобразуется в нижний регистр.

Пример:

@receiver(pre_save, sender=YourModel)
def convert_to_lowercase(sender, instance, *args, **kwargs):
    instance.lowercase_field = instance.lowercase_field.lower()
0 голосов
/ 28 февраля 2010

Вы пытаетесь присвоить field_name свойство и делаете что-либо в методе получения или установки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...