DjangoのcharFieldの末尾から空白(トリム)を削除するにはどうすればよいですか?
これが私のモデルです。ご覧のとおり、クリーンなメソッドを入力しようとしましたが、これらは実行されません。
name.strip()
、models.charField().strip()
も試してみましたが、どちらも機能しません。
CharFieldを強制的に自動的にトリミングする方法はありますか?
ありがとう。
from Django.db import models
from Django.forms import ModelForm
from Django.core.exceptions import ValidationError
import datetime
class Employee(models.Model):
"""(Workers, Staff, etc)"""
name = models.CharField(blank=True, null=True, max_length=100)
def save(self, *args, **kwargs):
try:
# This line doesn't do anything??
#self.full_clean()
Employee.clean(self)
except ValidationError, e:
print e.message_dict
super(Employee, self).save(*args, **kwargs) # Real save
# If I uncomment this, I get an TypeError: unsubscriptable object
#def clean(self):
# return self.clean['name'].strip()
def __unicode__(self):
return self.name
class Meta:
verbose_name_plural = 'Employees'
class Admin:pass
class EmployeeForm(ModelForm):
class Meta:
model = Employee
# I have no idea if this method is being called or not
def full_clean(self):
return super(Employee), self.clean().strip()
#return self.clean['name'].strip()
編集:コードを最新バージョンに更新しました。名前フィールドの空白が削除(トリミング)されていないため、何が間違っているのかわかりません。
モデルのクリーニングを呼び出す必要があるため(自動ではありません)、saveメソッドにself.full_clean()
を配置します。
http://docs.djangoproject.com/en/dev/ref/models/instances/#Django.db.models.Model.full_clean
フォームについては、削除されたクリーンなデータを返す必要があります。
_return self.cleaned_data['name'].strip()
_
どういうわけか、あなたはうまくいかないことをたくさんやろうとしただけだと思います。フォームとモデルは2つの非常に異なるものであることを忘れないでください。
フォームを検証する方法については、フォームのドキュメントを確認してください http://docs.djangoproject.com/en/dev/ref/forms/validation/
super(Employee), self.clean().strip() makes no sense at all!
修正されたコードは次のとおりです。
_class Employee(models.Model):
"""(Workers, Staff, etc)"""
name = models.CharField(blank=True, null=True, max_length=100)
def save(self, *args, **kwargs):
self.full_clean() # performs regular validation then clean()
super(Employee, self).save(*args, **kwargs)
def clean(self):
"""
Custom validation (read docs)
PS: why do you have null=True on charfield?
we could avoid the check for name
"""
if self.name:
self.name = self.name.strip()
class EmployeeForm(ModelForm):
class Meta:
model = Employee
def clean_name(self):
"""
If somebody enters into this form ' hello ',
the extra whitespace will be stripped.
"""
return self.cleaned_data.get('name', '').strip()
_
ModelFormインスタンスを使用してモデルを作成/編集している場合、モデルのclean()メソッドが呼び出されることが保証されています。したがって、フィールドから空白を削除する場合は、モデルにclean()メソッドを追加するだけです(ModelFormクラスを編集する必要はありません)。
class Employee(models.Model):
"""(Workers, Staff, etc)"""
name = models.CharField(blank=True, null=True, max_length=100)
def clean(self):
if self.name:
self.name = self.name.strip()
次のコードスニペットが便利だと思います。フィールドを個別に指定しなくても、CharFieldまたはTextFieldのいずれかをサブクラス化するモデルのすべてのフィールドの空白をトリミングします(したがって、これはURLFieldフィールドもキャッチします)。
def clean(self):
for field in self._meta.fields:
if isinstance(field, (models.CharField, models.TextField)):
value = getattr(self, field.name)
if value:
setattr(self, field.name, value.strip())
名前宣言でnull = Trueを使用してはならないことを誰かが正しく指摘しました。ベストプラクティスは、文字列フィールドに対してnull = Trueを回避することです。この場合、上記は次のように簡略化されます。
def clean(self):
for field in self._meta.fields:
if isinstance(field, (models.CharField, models.TextField)):
setattr(self, field.name, getattr(self, field.name).strip())
Django 1.9は、これを実現する簡単な方法を提供します。デフォルトがTrueであるstrip
引数を使用することにより、先頭と末尾の空白が確実に削除されるようにすることができます。ただし、ユーザー入力が確実にトリミングされるようにするために、フォームフィールドでのみこれを行うことができます。しかし、それでもモデル自体は保護されません。それでもそれを実行したい場合は、上記の方法のいずれかを使用できます。
詳細については、 https://docs.djangoproject.com/en/1.9/ref/forms/fields/#charfield をご覧ください。
トリミングするデータフィールドが非常に多い場合は、CharFieldを拡張してみませんか?
from Django.db import models
from Django.utils.translation import ugettext_lazy as _
class TrimCharField(models.CharField):
description = _(
"CharField that ignores leading"
" and trailing spaces in data")
def get_prep_value(self, value)
return trim(super(TrimCharField, self
).get_prep_value(value))
def pre_save(self, model_instance, add):
return trim(super(TrimCharField, self
).pre_save(model_instance, add))
更新:Djangoバージョン<= 1.7の場合、フィールドを拡張する場合は、models.SubfieldBaseメタクラスを使用する必要があります。したがって、ここでは次のようになります。
class TrimCharField(six.with_metaclass(
models.SubfieldBase, models.CharField)):
私はこれをデコレータとしてビューで処理しています。また、CharFieldのmax_length値を超えるフィールド値を切り捨てています。
from Django import forms
from Django import models
from Django.db.models.fields import FieldDoesNotExist
from Django.utils.encoding import smart_str
class CleanCharField(forms.CharField):
"""Django's default form handling drives me nuts wrt trailing
spaces. http://code.djangoproject.com/attachment/ticket/6362
"""
def clean(self, value):
if value is None:
value = u''
value = smart_str(value).strip()
value = super(forms.CharField, self).clean(value)
return value
def truncate_charfield(model):
"""decorator to truncate CharField data to model field max_length.
Apply to the clean method in views Form:
@truncate_charfield(MyModel)
def clean(self):
...
"""
def wrap(f):
def wrapped_f(*args):
f(*args)
d = args[0].cleaned_data
for field in model._meta.fields:
try:
mf = model._meta.get_field(field.name)
if isinstance(mf, models.CharField) and field.name in d:
d[field.name] = d[field.name][:mf.max_length]
except FieldDoesNotExist:
pass
return d
return wrapped_f
return wrap
あなたがまだDjango 1.9+あなた(そして私)に恥をかかせて、これをあなたのフォームにドロップしていない場合。これは@ jeremy-lewisの答えに似ていますが、私は彼にいくつかの問題がありました。
def clean_text_fields(self):
# TODO: Django 1.9, use on the model strip=True
# https://docs.djangoproject.com/en/1.9/ref/forms/fields/#charfield
from Django.forms.fields import CharField
cd = self.cleaned_data
for field_name, field in self.fields.items():
if isinstance(field, CharField):
cd[field_name] = cd[field_name].strip()
if self.fields[field_name].required and not cd[field_name]:
self.add_error(field_name, "This is a required field.")
def clean(self):
self.clean_text_fields()