Django TestCase on form validation fails even tough input is 有效
Django TestCase on form validation fails even tough input is valid
如标题中所述,当我使用 FormView
时,我有一个可以正确验证的表单。然而,当我今天开始编写测试时
相同的输入在 TestCase 中失败,我收到以下错误:
{'programming_language': ['Select a valid choice. That choice is not one of the available choices.']}
这些是我正在使用的模型、表单、视图和测试
# models.py
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=40, unique=True)
class ProgrammingLanguage(models.Model):
name = models.CharField(max_length=40, unique=True)
class Snippet(models.Model):
title = models.CharField(max_length=40)
programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE)
creation_date = models.DateTimeField(auto_now_add=True)
explanation = models.TextField()
code = models.TextField()
tags = models.ManyToManyField(Tag)
# forms.py
from django import forms
from django.utils.translation import gettext_lazy as _
from .models import Snippet
class SnippetForm(forms.ModelForm):
class Meta:
model = Snippet
exclude = ["creation_date"]
# views.py
from django.urls import reverse_lazy
from django.views import generic
from .models import Snippet
from .forms import SnippetForm
class SnippetFormView(generic.FormView):
template_name = "snippets/snippet_form.html"
form_class = SnippetForm
success_url = reverse_lazy("snippets")
def form_valid(self, form):
# for testing purposes
print(form.cleaned_data)
form.save()
return super().form_valid(form)
# test_forms.py
from django.test import TestCase
from snippets.forms import SnippetForm
from snippets.models import ProgrammingLanguage, Tag, Snippet
class SnippetFormTestCase(TestCase):
@classmethod
def setUpTestData(cls):
ProgrammingLanguage.objects.create(name="Javascript")
Tag.objects.create(name="website")
def test_forms(self):
form = SnippetForm({
'title': 'Test snippet title',
'programming_language': ProgrammingLanguage.objects.get(pk=1),
'code': 'code here',
'explanation': 'explanation here',
'tags': Tag.objects.all()
})
# calling is valid to get cleaned_data and original data
form.is_valid()
print(form.data)
print(form.cleaned_data)
self.assertEqual(form.errors, {})
这是cleaned_data
我在视图中得到的:
{'title': 'Test snippet title', 'programming_language': <ProgrammingLanguage: Javascript>, 'explanation': 'explanation here', 'code': 'code here', 'tags': <QuerySet [<Tag: website>]>}
这是我在测试中得到的数据和 cleaned_data:
# data
{'title': 'Test snippet title', 'programming_language': <ProgrammingLanguage: Javascript>, 'code': 'code here', 'explanation': 'explanation here', 'tags': <QuerySet [<Tag: website>]>}
# cleaned_data
{'title': 'Test snippet title', 'explanation': 'explanation here', 'code': 'code here', 'tags': <QuerySet [<Tag: website>]>}
为什么 ProgrammingLanguage 在测试期间是无效的选择,但在使用网站时有效?
在你的测试中试试这个:
form = SnippetForm({
'title': 'Test snippet title',
'programming_language': 1, #ProgrammingLanguage.objects.get(pk=1),
'code': 'code here',
'explanation': 'explanation here',
'tags': Tag.objects.all()
})
当将表单用于将主键作为其字段之一的模型时,您使用此类字段的 pk 值将表单绑定到数据,而不是模型实例。
这就是 FormView
在幕后所做的事情。这就是为什么您的测试失败而视图工作正常的原因。
还要确保您的编程语言 pk
是 1.
如标题中所述,当我使用 FormView
时,我有一个可以正确验证的表单。然而,当我今天开始编写测试时
相同的输入在 TestCase 中失败,我收到以下错误:
{'programming_language': ['Select a valid choice. That choice is not one of the available choices.']}
这些是我正在使用的模型、表单、视图和测试
# models.py
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=40, unique=True)
class ProgrammingLanguage(models.Model):
name = models.CharField(max_length=40, unique=True)
class Snippet(models.Model):
title = models.CharField(max_length=40)
programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE)
creation_date = models.DateTimeField(auto_now_add=True)
explanation = models.TextField()
code = models.TextField()
tags = models.ManyToManyField(Tag)
# forms.py
from django import forms
from django.utils.translation import gettext_lazy as _
from .models import Snippet
class SnippetForm(forms.ModelForm):
class Meta:
model = Snippet
exclude = ["creation_date"]
# views.py
from django.urls import reverse_lazy
from django.views import generic
from .models import Snippet
from .forms import SnippetForm
class SnippetFormView(generic.FormView):
template_name = "snippets/snippet_form.html"
form_class = SnippetForm
success_url = reverse_lazy("snippets")
def form_valid(self, form):
# for testing purposes
print(form.cleaned_data)
form.save()
return super().form_valid(form)
# test_forms.py
from django.test import TestCase
from snippets.forms import SnippetForm
from snippets.models import ProgrammingLanguage, Tag, Snippet
class SnippetFormTestCase(TestCase):
@classmethod
def setUpTestData(cls):
ProgrammingLanguage.objects.create(name="Javascript")
Tag.objects.create(name="website")
def test_forms(self):
form = SnippetForm({
'title': 'Test snippet title',
'programming_language': ProgrammingLanguage.objects.get(pk=1),
'code': 'code here',
'explanation': 'explanation here',
'tags': Tag.objects.all()
})
# calling is valid to get cleaned_data and original data
form.is_valid()
print(form.data)
print(form.cleaned_data)
self.assertEqual(form.errors, {})
这是cleaned_data
我在视图中得到的:
{'title': 'Test snippet title', 'programming_language': <ProgrammingLanguage: Javascript>, 'explanation': 'explanation here', 'code': 'code here', 'tags': <QuerySet [<Tag: website>]>}
这是我在测试中得到的数据和 cleaned_data:
# data
{'title': 'Test snippet title', 'programming_language': <ProgrammingLanguage: Javascript>, 'code': 'code here', 'explanation': 'explanation here', 'tags': <QuerySet [<Tag: website>]>}
# cleaned_data
{'title': 'Test snippet title', 'explanation': 'explanation here', 'code': 'code here', 'tags': <QuerySet [<Tag: website>]>}
为什么 ProgrammingLanguage 在测试期间是无效的选择,但在使用网站时有效?
在你的测试中试试这个:
form = SnippetForm({
'title': 'Test snippet title',
'programming_language': 1, #ProgrammingLanguage.objects.get(pk=1),
'code': 'code here',
'explanation': 'explanation here',
'tags': Tag.objects.all()
})
当将表单用于将主键作为其字段之一的模型时,您使用此类字段的 pk 值将表单绑定到数据,而不是模型实例。
这就是 FormView
在幕后所做的事情。这就是为什么您的测试失败而视图工作正常的原因。
还要确保您的编程语言 pk
是 1.