我有以下型号:
class Student(models.Model):
first_name = models.CharField(verbose_name='student first name', max_length=64)
last_name = models.CharField(verbose_name='student last name', max_length=64)
email = models.EmailField()
class Meta:
db_table = 'student'
def __str__(self):
return self.first_name + ' ' + self.last_name
class Course(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
start_date = models.DateField(null=True, blank=True, default=None)
end_date = models.DateField(null=True, blank=True, default=None)
class Meta:
db_table = 'course'
def __str__(self):
return self.name
class CourseParticipant(models.Model):
course = models.ForeignKey(Course, related_name='courses', on_delete=models.CASCADE)
student = models.ForeignKey(Student, related_name='student_name', on_delete=models.CASCADE)
completed = models.BooleanField(null=False, default=False)
class Meta:
db_table = 'course_participant'
def __str__(self):
return self.course, self.student
网址:
app_name = 'student'
urlpatterns = [
path(
'student', StudentAPIView.as_view(),
name='list'
),
path(
'student/detail/<int:pk>/',
StudentAPIDetailView.as_view(),
name='detail'
),
path(
'student/assign_student_to_course',
StudentAPIAssignToCourse.as_view(),
name='assign_student_to_course'
),
path(
'student/assigned_to_course',
StudentAPIAssignedToTheCourseView.as_view(),
name='assigned_to_course_list'
),
path(
'student/assigned_to_course/detail/<int:pk>/',
StudentAPIUnassignedFromTheCourseView.as_view(),
name='unassigned_to_course_list'
),
path(
'student/report/<int:pk>/',
StudentAPIPerformanceReport.as_view(),
name='student_performance'
)
]
观看次数:
import csv
from django.http import HttpResponse
from rest_framework import mixins, generics
from course.models import (
CourseParticipant
)
from student.models import (
Student
)
from student.serializers import (
StudentSerializer, AssignStudentToCourseSerializer, StudentAssignedToTheCourseSerializer
)
class StudentAPIView(
mixins.CreateModelMixin,
generics.ListAPIView
):
serializer_class = StudentSerializer
def get_queryset(self):
queryset = Student.objects.all()
return queryset
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class StudentAPIDetailView(
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.RetrieveAPIView,
):
serializer_class = StudentSerializer
def get_queryset(self):
query_set = Student.objects.all()
return query_set
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
class StudentAPIAssignToCourse(
generics.CreateAPIView
):
serializer_class = AssignStudentToCourseSerializer
def get_queryset(self):
queryset = CourseParticipant.objects.all()
return queryset
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class StudentAPIAssignedToTheCourseView(
generics.ListAPIView
):
serializer_class = StudentAssignedToTheCourseSerializer
def get_queryset(self):
queryset = CourseParticipant.objects.all()
return queryset
class StudentAPIUnassignedFromTheCourseView(
mixins.DestroyModelMixin,
generics.RetrieveAPIView,
):
serializer_class = StudentAssignedToTheCourseSerializer
def get_queryset(self):
queryset = CourseParticipant.objects.all()
return queryset
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
class StudentAPIPerformanceReport(
generics.RetrieveAPIView,
):
def get(self, request, *args, **kwargs):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="report.csv"'
writer = csv.writer(response)
for student in Student.objects.filter(pk=self.kwargs['pk']):
assigned_courses = CourseParticipant.objects.filter(student=student)
completed_courses = assigned_courses.filter(completed=True)
headings = (
"student full Name",
"number of assigned courses to student",
"number of completed courses by student"
)
rows = (
student.full_name,
assigned_courses.count(),
completed_courses.count()
)
writer.writerow(headings)
writer.writerow(rows)
return response
并对其进行测试:
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework.reverse import reverse as api_reverse
from course.models import CourseParticipant
from .models import Student
class StudentAPITestCase(APITestCase):
def setUp(self):
student_obj = Student.objects.create(
first_name='test',
last_name='student',
email='test_student@gmail.com',
)
def create_item(self):
url = api_reverse('student:list')
data = {
'first_name': 'some_first_name_for_test',
'last_name': 'some_last_name_for_test',
'email': 'test_student@gmail.com'
}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Student.objects.count(), 2)
return response.data
def test_student_create(self):
data = self.create_item()
data_id = data.get('id')
rud_url = api_reverse('student:detail', kwargs={'pk': data_id})
rud_data = {
'first_name': 'some_new_first_name_for_test',
'last_name': 'some_new_last_name_for_test'
}
get_response = self.client.get(rud_url, rud_data, format='json')
self.assertEqual(get_response.status_code, status.HTTP_200_OK)
def test_student_update(self):
data = self.create_item()
data_id = data.get('id')
rud_url = api_reverse('student:detail', kwargs={'pk': data_id})
rud_data = {
'first_name': 'some_new_first_name_for_test',
'last_name': 'some_new_last_name_for_test',
'email': 'test_student@gmail.com'
}
put_response = self.client.put(rud_url, rud_data, format='json')
self.assertEqual(put_response.status_code, status.HTTP_200_OK)
def test_student_delete(self):
data = self.create_item()
data_id = data.get('id')
rud_url = api_reverse('student:detail', kwargs={'pk': data_id})
delete_response = self.client.delete(rud_url, data_id, format='json')
self.assertEqual(delete_response.status_code, status.HTTP_204_NO_CONTENT)
get_response = self.client.delete(rud_url, format='json')
self.assertEqual(get_response.status_code, status.HTTP_404_NOT_FOUND)
class StudentAssignToCourseAPITestCase(APITestCase):
def setUp(self):
student_obj = CourseParticipant.objects.create(
course_id=1,
student_id=1,
)
def test_create_item(self):
url = api_reverse('student:assign_student_to_course')
data = {
'course_id': 1,
'student_id': 1,
}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Student.objects.count(), 2)
return response.data
通过了StudentAPITestCase的所有测试,但是来自StudentAssignToCourseAPITestCase的测试失败,并带有一些Traceback:
回溯(最近通话最近): 在调用中的第274行中,文件“/home/leonidsoputnyak/Документы/project/test_task/venv/lib/python3.7/site-packages/django/test/testcases.py” self._post_teardown() _post_teardown中的第1009行,文件“/home/leonidsoputnyak/Документы/project/test_task/venv/lib/python3.7/site-packages/django/test/testcases.py” self._fixture_teardown() 文件“/home/leonidsoputnyak/Документы/project/test_task/venv/lib/python3.7/site-packages/django/test/testcases.py”,行1177,在_fixture_teardown中 连接[db_name] .check_constraints() 文件“/home/leonidsoputnyak/Документы/project/test_task/venv/lib/python3.7/site-packages/django/db/backends/sqlite3/base.py”,行318,在check_constraints中 坏值,引用表名称,引用列名称 django.db.utils.IntegrityError:表'course_participant'中具有主键'1'的行具有无效的外键:course_participant.student_id包含的值'1'在student.id中没有相应的值。>
有人可以解释为什么我从StudentAssignTo课程APITestCase进行的测试失败以及我如何解决该问题吗?
答案 0 :(得分:2)
在尝试使用不存在的student_id值创建setUp
的{{1}}方法中,测试失败。因此,您应该首先创建CourseParticipant
和User
对象并使用其ID:
Course