1

我有两个模型,我正在做一个自定义表单,这样我就可以查看表单并将其从我的 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.

模型.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)

表格.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',)

视图.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)

非常感谢。

4

3 回答 3

3

问题不在于保存,而在于验证您的表单。基本上,您为 Book 创建模型表单的自定义版本,其中包含两个字段authortitle. 默认情况下,该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

一个非常相似的问题是如何更改方法 is_valid() 中的表单字段

于 2013-04-04T13:52:49.147 回答
2

我尝试了您的代码并进行了一些测试,无论我做什么,我总是会遇到该错误。因为在作者创建之前,书先执行,导致实例错误。

我修改了你的代码。我删除了您的保存方法并将其更改为现在有效的清洁方法。

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',)
于 2013-04-04T11:32:03.057 回答
0

问题是它甚至没有访问设置作者实例的代码,因为超类的保存方法使用文本字段将其设置在那里,这是错误发生的地方。

您可以尝试使用在调用 super 之前pop删除该authorcleaned_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)
于 2013-04-04T13:00:38.580 回答