Django REST framework. APITestCase. Как исправить 'bad_value, referenced_table_name, referenced_column_name' - PullRequest
0 голосов
/ 04 июля 2019

У меня есть следующие модели:

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

URL:

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 завершился неудачно с некоторой трассировкой:

Трассировка (последний из последних вызовов): Файл "/ home / leonidsoputnyak / Документы / project / test_task /venv / lib / python3.7 / site-packages / django / test / testcases.py ", строка 274, в вызов self._post_teardown () файл" / home / leonidsoputnyak / Документы / project / test_task /venv / lib / python3.7 / site-packages / django / test / testcases.py ", строка 1009, в файле _post_teardown 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 / Джанго / дб / бэкэнды / sqlite3 / base.py"строка 318, в check_constraints bad_value, referenced_table_name, referenced_column_name django.db.utils.IntegrityError: строка в таблице 'course_participant' с первичным ключом '1' имеет недопустимый внешний ключ: course_participant.student_id содержит значение '1', которое делаетне имеют соответствующего значения в student.id.

Может кто-нибудь объяснить, почему мой тест из StudentAssignTo Course APITestCase не проходит и как я могу это исправить?

1 Ответ

2 голосов
/ 04 июля 2019

Тест не пройден, поскольку в методе setUp вы пытаетесь создать CourseParticipant с несуществующим значением student_id. Поэтому вы должны сначала создать User и Course объекты и использовать их идентификаторы:

class StudentAssignToCourseAPITestCase(APITestCase):
    def setUp(self):
        self.student_obj = Student.objects.create(
            first_name='test',
            last_name='student',
            email='test_student@gmail.com',
        )
        self.course_obj = Course.objects.create(
            # couse's attribute here
        )
        student_obj = CourseParticipant.objects.create(
            course_id=self.course_obj.pk,
            student_id=self.student_obj.pk,
        )

    def test_create_item(self):
        url = api_reverse('student:assign_student_to_course')
        data = {
            'course_id': self.course_obj.pk,
            'student_id': self.student_obj.pk,

        }
        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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...