在我的Django应用程序中,我使用ModelForm让我的用户输入街道地址。
我想要清理这个地址,对它执行USPS验证,然后对其进行地理编码。如果所有这些步骤都成功,我想将脏的和已清理的版本保存到我的Location
模型中,如下所示。
from localflavor.us.us_states import US_STATES
from django.contrib.gis.db import models
class Location(models.Model):
# I want the user to enter these fields using a Model Form
streetAddress = models.CharField(blank=False, null=False, max_length=300)
city = models.CharField(null=False, blank=False, max_length=50)
state = USStateField(choices = US_STATES, null=False,)
zip = models.CharField(null=False, max_length=10, )
# I want to automatically derive these fields without any user intervention.
# These fields are going to be calculated during the form validation process.
cleanedStreetAddress = models.CharField(blank=False, null=False, max_length=300)
cleanedCity = models.CharField(null=True, blank=True, max_length=50)
cleanedState = USStateField(choices = US_STATES, null=False,)
cleanedZip5 = models.CharField(null=False, max_length=5, )
cleanedZip4 = models.CharField(null=False, max_length=4, )
geoCoords = models.PointField(null=False, blank=False,)
在我对应的ModelForm(名为LocationForm
)中,我有fields = ["streetAddress", "city", "state", "zip",]
。我通过手动将它们添加到LocationForm.clean()
方法返回的字典中来填充剩余的6个字段。到现在为止还挺好。没问题。
在相应的基于类的视图中,我使用form_valid()
方法处理表单,如下所示:
class InputLocationView(FormView):
template_name = "helloWorld.html"
form_class = LocationForm
success_url = "/helloWorld"
def form_valid(self, form):
print "form.cleaned_data = %s" % form.cleaned_data
###
# Output of the line above:
# form.cleaned_data = {'cleanedZip4': '0000', 'streetAddress': u'123 Main Street',
# 'zip': u'90210', 'cleanedStreetAddress': '123 MAIN ST', 'cleanedState': 'CO',
# 'geoCoords': <Point object at 0x10a1b4e20>, 'state': u'CO', 'city': u'Anytown',
# 'cleanedCity': 'ANYTOWN', 'cleanedZip5': '90210'}
###
print "form.cleaned_data['geoCoords'] = (%s, %s)" % (form.cleaned_data['geoCoords'].x, form.cleaned_data['geoCoords'].y)
# Output of the line above: form.cleaned_data['geoCoords'] = (-77.260768, 39.113707)
newLocation = form.save(commit=False)
newLocation.save()
从上面的评论中可以看出,我在LocationForm.clean()中添加的派生数据存在于基于类的视图中。这是个好消息。但是,当它到达newLocation.save()时,会出现以下错误:
null value in column "geoCoords" violates not-null constraint
DETAIL: Failing row contains (3, 123 Main Street, , Anytown, CO, 90210, , null,
, , , null)
为什么newLocation.save()
不包括我的任何派生数据,显然form.cleaned_data
词典中存在所有数据?如何确保来自form.cleaned_data
的所有数据进入SQL Insert语句?
答案 0 :(得分:1)
ModelForm
机制可能只填写您在fields
中指定的实例字段。我解决这个问题的方法是覆盖ModelForm.save()
。像这样:
class LocationForm(ModelForm):
...
def save(self, commit=True, **kwargs):
# create the instance but don't commit it to the database
location = super(LocationForm, self).save(commit=False, **kwargs)
# now set your cleaned fields on the model instance
location.cleanedStreetAddress = ...
if commit:
location.save()
return location
有关详细信息,请参阅documentation on save()
。
答案 1 :(得分:0)
如果我没有记错的话,只会从ModelForm.Meta.fields
自动分配cleaned_data
列表中指定的字段。您应该直接在cleaned_data
中的self.instance
上设置,而不是将您的派生数据放入ModelForm
。