我有两个模型,我正在做一个自定义表单,以便我可以查看并将表单从我的HTML保存到数据库中。但是当我尝试保存时,我得到了这个错误。
回溯
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8008/
Django Version: 1.4
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'SecondBlog.blog',
'django.contrib.admin',
'django.contrib.admindocs')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "c:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "f:\apt3\SecondBlog\SecondBlog\blog\views.py" in home
10. if form.is_valid():
File "c:\Python27\lib\site-packages\django\forms\forms.py" in is_valid
124. return self.is_bound and not bool(self.errors)
File "c:\Python27\lib\site-packages\django\forms\forms.py" in _get_errors
115. self.full_clean()
File "c:\Python27\lib\site-packages\django\forms\forms.py" in full_clean
272. self._post_clean()
File "c:\Python27\lib\site-packages\django\forms\models.py" in _post_clean
309. self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
File "c:\Python27\lib\site-packages\django\forms\models.py" in construct_instance
51. f.save_form_data(instance, cleaned_data[f.name])
File "c:\Python27\lib\site-packages\django\db\models\fields\__init__.py" in save_form_data
454. setattr(instance, self.name, data)
File "c:\Python27\lib\site-packages\django\db\models\fields\related.py" in __set__
366. self.field.name, self.field.rel.to._meta.object_name))
Exception Type: ValueError at /
Exception Value: Cannot assign "u'Sasa'": "Book.author" must be a "Author" instance.
models.py
class Author(models.Model):
name = models.CharField(max_length = 30)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length = 100)
def __unicode__(self):
return '%s' % (self.title)
forms.py
class CustomForm(ModelForm):
author = forms.CharField()
def save(self, commit=True):
author = Author.objects.get_or_create(name=self.cleaned_data['author'])
instance = super(CustomForm, self).save(commit=commit)
instance.author = author
if commit:
instance.save()
return instance
class Meta:
model = Book
fields = ('author','title',)
views.py
def home(request):
if request.method == 'POST':
form = CustomForm(request.POST)
if form.is_valid():
print "all validated"
form.save()
return HttpResponseRedirect('index.html')
else:
print "failed"
else:
form = CustomForm()
variables = RequestContext(request, {'form' : form})
return render_to_response('index.html', variables)
非常感谢你。
答案 0 :(得分:3)
问题不在于保存,而在于验证表单。基本上,您可以为Book创建模型表单的自定义版本,其中包含两个字段author
和title
。默认情况下,author
字段将显示为作者类型的参考浏览窗口小部件。
但是,对author = forms.CharField()
执行的操作是告诉表单显示简单的文本输入字段而不是作者引用选择器。当它试图验证这个......好吧它不能。
您需要做的是在验证前处理author
值,您可以在clean()
函数中执行此操作,您可以将其添加到CustomForm
def clean(self):
self.cleaned_data['author'] = Author.objects.get_or_create(name=self.cleaned_data['author'])
return self.cleaned_data
一个非常类似的问题出现在how to change form field in method is_valid()
中答案 1 :(得分:1)
我尝试你的代码并做一些测试,不管我做什么,我总是得到那个错误。因为在作者创建之前,书首先执行导致实例错误。
我修改了你的代码。我删除了你的保存方法并将其更改为现在正在运行的clean方法。
class CustomForm(forms.ModelForm):
author = forms.CharField()
def clean(self):
cleaned_data = super(CustomForm, self).clean()
author = cleaned_data.get("author")
if not author:
raise forms.ValidationError("Please enter an author")
data = Author.objects.create(name=author)
cleaned_data['author'] = data
return cleaned_data
class Meta:
model = Book
fields = ('author','title',)
答案 2 :(得分:0)
问题在于它甚至没有找到设置作者实例的代码,因为超类的save方法是使用文本字段将其设置在那里,这是发生错误的地方。
您可以尝试使用pop
在调用super之前从author
中删除cleaned_data
值,或者使用Author实例替换该值。
编辑例如
def save(self, commit=True):
author = Author.objects.get_or_create(name=self.cleaned_data.pop('author'))
instance = super(CustomForm, self).save(commit=commit)