** edit 11/30/2015:在python 3中,不再支持 module-global __metaclass__
变量。Additionaly,为的阶级被弃用:Django 1.10
SubfieldBase
django.db.models.fields.subclassing.SubfieldBase
已被弃用,并将在Django 1.10中删除。从历史上看,它用于处理从数据库加载时需要类型转换的字段,但未在.values()
调用或聚合中使用。已替换为from_db_value()
。
请注意,新方法不会像那样调用to_python()
赋值方法SubfieldBase
。
因此,如from_db_value()
文档和此示例所建议,此解决方案必须更改为:
class CharNullField(models.CharField):
"""
Subclass of the CharField that allows empty strings to be stored as NULL.
"""
description = "CharField that stores NULL but returns ''."
def from_db_value(self, value, expression, connection, contex):
"""
Gets value right out of the db and changes it if its ``None``.
"""
if value is None:
return ''
else:
return value
def to_python(self, value):
"""
Gets value right out of the db or an instance, and changes it if its ``None``.
"""
if isinstance(value, models.CharField):
# If an instance, just return the instance.
return value
if value is None:
# If db has NULL, convert it to ''.
return ''
# Otherwise, just return the value.
return value
def get_prep_value(self, value):
"""
Catches value right before sending to db.
"""
if value == '':
# If Django tries to save an empty string, send the db None (NULL).
return None
else:
# Otherwise, just pass the value.
return value
我认为,比在admin中覆盖cleaned_data更好的方法是将charfield子类化-这种方法无论以何种形式访问该字段,都将“正常工作”。您可以''
在将其发送到数据库之前捕获NULL,并在将其从数据库中删除之后立即捕获NULL,而Django的其余部分将不知道/不在乎。一个简单而肮脏的例子:
from django.db import models
class CharNullField(models.CharField): # subclass the CharField
description = "CharField that stores NULL but returns ''"
__metaclass__ = models.SubfieldBase # this ensures to_python will be called
def to_python(self, value):
# this is the value right out of the db, or an instance
# if an instance, just return the instance
if isinstance(value, models.CharField):
return value
if value is None: # if the db has a NULL (None in Python)
return '' # convert it into an empty string
else:
return value # otherwise, just return the value
def get_prep_value(self, value): # catches value right before sending to db
if value == '':
# if Django tries to save an empty string, send the db None (NULL)
return None
else:
# otherwise, just pass the value
return value
对于我的项目,我将其转储到位于extras.py
网站根目录中的文件中,然后可以将其from mysite.extras import CharNullField
放在应用程序的models.py
文件中。该字段的行为就像CharField一样-请记住blank=True, null=True
在声明该字段时进行设置,否则Django将抛出验证错误(必填字段)或创建一个不接受NULL的db列。
def get_db_prep_value(self, value, connection, prepared=False)
作为方法调用。请访问groups.google.com/d/msg/django-users/Z_AXgg2GCqs/zKEsfu33OZMJ了解更多信息。以下方法也适用于我:def get_prep_value(self,value):if value ==“”:#如果Django尝试保存''字符串,则发送db None(NULL)return None:返回值#否则,仅传递值