我一直在为这个问题挠头。我正在尝试构建一个自定义模型字段来存储邮政地址。
总体思路是将序列化后的所有数据存储在 amodels.TextField
中,并使用 aform.MultiValueField
来捕获每个值。
出于某种原因,即使迁移工作正常,在管理员中,该字段也会显示为简单的TextField
. 好像这MultiValueField
部分被完全忽略了......
这是我的代码:
from django.db import models
from django.forms import MultiValueField, CharField
from django.utils.translation import ugettext_lazy as _
class Address(object):
"""A postal address."""
def __init__(self, street, postal_code, city,
country, complement=None, region=None):
self.street = street
self.complement = complement
self.postal_code = postal_code
self.city = city
self.region = region
self.country = country
def print_address_inline(self):
complement = ''
region = ''
if self.complement:
complement = ', %s' % self.complement
if self.region:
region = ', %s' % self.region
data = {
'street': self.street,
'complement': complement,
'code': self.postal_code,
'city': self.city,
'region': region,
'country': self.country
}
return '%(street)s%(complement)s, %(code)s %(city)s%(region)s' \
', %(country)s' % data
def __str__(self):
return self.print_address_inline()
class AddressFormField(MultiValueField):
def __init__(self, *args, **kwargs):
del kwargs['max_length']
error_messages = {
'incomplete': _('Enter a complete address: ' \
'street, postal code, city and country.'),
}
fields = (
CharField(
label='street', max_length=1024,
error_messages={
'incomplete': _('Enter the number and street.')
}
),
CharField(
label='complement', max_length=1024, required=False
),
CharField(
label='code', max_length=10,
error_messages={'incomplete': _('Enter the postal code.')}
),
CharField(
label='city', max_length=255,
error_messages={'incomplete': _('Enter the city.')}
),
CharField(
label='region', max_length=255, required=False
),
CharField(
label='country', max_length=255,
error_messages={'incomplete': _('Enter the country.')}
)
)
super(AddressFormField, self).__init__(
error_messages=error_messages, fields=fields,
require_all_fields=False, *args, **kwargs
)
def compress(self, data_list):
if data_list:
if data_list[0] in self.empty_values:
raise ValidationError(
_('Enter the number and street.'),
code='incomplete'
)
if data_list[2] in self.empty_values:
raise ValidationError(
_('Enter the postal code.'),
code='incomplete'
)
if data_list[3] in self.empty_values:
raise ValidationError(
_('Enter the city.'),
code='incomplete'
)
if data_list[5] in self.empty_values:
raise ValidationError(
_('Enter the country.'),
code='incomplete'
)
address = Address(
street=data_list[0],
complement=data_list[1],
code=data_list[2],
city=data_list[3].title(),
region=data_list[4],
country=data_list[5].upper()
)
return address
return None
class AddressField(models.TextField):
description = "A postal address."
def __init__(self, *args, **kwargs):
super(AddressField, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(AddressField, self).deconstruct()
return name, path, args, kwargs
def from_db_value(self, value, expression, connection, context):
if value is None:
return value
data = value.split('@@')
return Address(*data)
def to_python(self, value):
if isinstance(value, Address):
return value
if value is None:
return value
data = value.split('@@')
return Address(*data)
def get_prep_value(self, value):
if isinstance(value, Address):
data = []
for v in [
value.street,
value.complement,
value.postal_code,
value.city,
value.region,
value.country,
]:
if v is not None:
data.append(v)
else:
data.append('')
return '@@'.join(data)
else:
return value
def formfield(self, **kwargs):
defaults = {'form_class': AddressFormField}
defaults.update(kwargs)
return super(AddressField, self).formfield(**defaults)
如果你有任何线索...
谢谢!