Django LowerCaseCharField
мы реализовали 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 ответов
вы можете переопределить 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")
Edit:
перечитывая ваш вопрос, похоже, вы хотите, чтобы снижение вступило в силу немедленно. Для этого вам нужно создать дескриптор (объект python нового стиля с __get__
и __set__
методы, см. документы 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))
использование свойств Python не является простым из-за способа django.модели.Модели волшебным образом устанавливают свои атрибуты экземпляра на основе атрибутов класса. Есть открываем ошибки для этого.
Я закончил тем, что сделал именно то, что сделал оригинальный плакат.
это означает, что вы должны сделать:
>>> modelinstance.field_name="TEST"
>>> modelinstance.save() # Extra step
>>> print modelinstance.field_name
'test'
вы пытаетесь сделать field_name a свойства и делать все, что в геттер или сеттер.
другой способ сделать это - добавить pre_save подключитесь к своей модели, а затем просто преобразуйте все поля, которые вы хотите записать в нижний регистр, используя lower(). Это обсуждается здесь по-другому. Таким образом, при сохранении объекта его поле преобразуется в нижний регистр.
пример:
@receiver(pre_save, sender=YourModel)
def convert_to_lowercase(sender, instance, *args, **kwargs):
instance.lowercase_field = instance.lowercase_field.lower()