Django:View 和 View-Test 相互对抗
Django: View and View-Test working against each other
现在我正在尝试测试我的一个非常简单的视图 - 它工作得很好 - 并收到一个错误:
Traceback (most recent call last):
File "C:\Users\someone\Documents\django_tests\app\tests\test_views.py", line 42, in test_person_post
ValueError: Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x00000262BBE2CF10>>": "Person.created_from" must be a "CustomUser" instance.
我已经将默认值 auth.user.model 更改为 AbstractUser 并将其更改为 mail/password-,而不是username/password-combination.
models.py:
class Person(models.Model):
GENDERS = (
('-', '-'),
('Diverse', 'Diverse'),
('Female', 'Female'),
('Male', 'Male'),
)
first_name = models.CharField(max_length=50, null=False, blank=False)
last_name = models.CharField(max_length=50, null=False, blank=False)
gender = models.CharField(max_length=10, null=False, blank=False, choices=GENDERS, default=GENDERS[0][1])
born = models.DateField(null=False, blank=False)
adult = models.BooleanField(default=False)
created_from = models.ForeignKey(USER, null=False, blank=False, on_delete=models.CASCADE)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['last_name', 'first_name']
constraints = [
models.UniqueConstraint(fields=['last_name', 'first_name'], name="unique person constraint"),
]
verbose_name = "Person"
verbose_name_plural = "Persons"
def get_absolute_url(self):
return f"api/persons/{self.id}/"
def __str__(self) -> str:
return f"{self.first_name} {self.last_name}"
forms.py:
class PersonForm(ModelForm):
class Meta:
model = Person
exclude = [
'id',
'adult',
'created_from',
'created_date',
'updated_date',
]
views.py:
def index(request):
form = PersonForm()
if request.method == 'POST':
form = PersonForm(request.POST)
if form.is_valid():
person = form.save(commit=False)
person.created_from = request.user
person.save()
return redirect('index')
context = {'form': form}
return render(request, 'app/index.html', context)
test_views.py:
USER = get_user_model()
class TestViews(TestCase):
def setUp(self):
self.user = USER.objects.create_user('test@email.com', 'testpassword')
self.client = Client()
self.persons_get_post = reverse('index')
def test_person_post(self):
response = self.client.post(self.persons_get_post, {
'first_name': 'Jane',
'last_name': 'Doe',
'gender': 'Female',
'born': datetime.date(1900, 1, 1),
'adult': True,
'created_from': self.user,
'created_date': timezone.now(),
'updated_date': timezone.now()
})
self.assertEquals(response.status_code, 302)
self.assertEquals(self.person_obj.expenses.first().first_name, 'Jane')
index.html:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django | Tests</title>
</head>
<body>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
</body>
</html>
问题:
当视图本身运行良好时,为什么测试文件会抛出此错误或我做错了什么?
好的,所以我找到了解决方案:test-view 默认将数据发送为 json,所以我只需要 change/add,就是header 我的 test_views.py:
def test_person_post(self):
response = self.client.post(self.persons_get_post, {
'first_name': 'Jane',
'last_name': 'Doe',
'gender': 'Female',
'born': datetime.date(1900, 1, 1),
'adult': True,
'created_from': self.user,
'created_date': timezone.now(),
'updated_date': timezone.now()
}, content_type='application/x-www-form-urlencoded')
self.assertEquals(response.status_code, 200)
现在我正在尝试测试我的一个非常简单的视图 - 它工作得很好 - 并收到一个错误:
Traceback (most recent call last):
File "C:\Users\someone\Documents\django_tests\app\tests\test_views.py", line 42, in test_person_post
ValueError: Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x00000262BBE2CF10>>": "Person.created_from" must be a "CustomUser" instance.
我已经将默认值 auth.user.model 更改为 AbstractUser 并将其更改为 mail/password-,而不是username/password-combination.
models.py:
class Person(models.Model):
GENDERS = (
('-', '-'),
('Diverse', 'Diverse'),
('Female', 'Female'),
('Male', 'Male'),
)
first_name = models.CharField(max_length=50, null=False, blank=False)
last_name = models.CharField(max_length=50, null=False, blank=False)
gender = models.CharField(max_length=10, null=False, blank=False, choices=GENDERS, default=GENDERS[0][1])
born = models.DateField(null=False, blank=False)
adult = models.BooleanField(default=False)
created_from = models.ForeignKey(USER, null=False, blank=False, on_delete=models.CASCADE)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['last_name', 'first_name']
constraints = [
models.UniqueConstraint(fields=['last_name', 'first_name'], name="unique person constraint"),
]
verbose_name = "Person"
verbose_name_plural = "Persons"
def get_absolute_url(self):
return f"api/persons/{self.id}/"
def __str__(self) -> str:
return f"{self.first_name} {self.last_name}"
forms.py:
class PersonForm(ModelForm):
class Meta:
model = Person
exclude = [
'id',
'adult',
'created_from',
'created_date',
'updated_date',
]
views.py:
def index(request):
form = PersonForm()
if request.method == 'POST':
form = PersonForm(request.POST)
if form.is_valid():
person = form.save(commit=False)
person.created_from = request.user
person.save()
return redirect('index')
context = {'form': form}
return render(request, 'app/index.html', context)
test_views.py:
USER = get_user_model()
class TestViews(TestCase):
def setUp(self):
self.user = USER.objects.create_user('test@email.com', 'testpassword')
self.client = Client()
self.persons_get_post = reverse('index')
def test_person_post(self):
response = self.client.post(self.persons_get_post, {
'first_name': 'Jane',
'last_name': 'Doe',
'gender': 'Female',
'born': datetime.date(1900, 1, 1),
'adult': True,
'created_from': self.user,
'created_date': timezone.now(),
'updated_date': timezone.now()
})
self.assertEquals(response.status_code, 302)
self.assertEquals(self.person_obj.expenses.first().first_name, 'Jane')
index.html:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Django | Tests</title>
</head>
<body>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
</body>
</html>
问题:
当视图本身运行良好时,为什么测试文件会抛出此错误或我做错了什么?
好的,所以我找到了解决方案:test-view 默认将数据发送为 json,所以我只需要 change/add,就是header 我的 test_views.py:
def test_person_post(self):
response = self.client.post(self.persons_get_post, {
'first_name': 'Jane',
'last_name': 'Doe',
'gender': 'Female',
'born': datetime.date(1900, 1, 1),
'adult': True,
'created_from': self.user,
'created_date': timezone.now(),
'updated_date': timezone.now()
}, content_type='application/x-www-form-urlencoded')
self.assertEquals(response.status_code, 200)