Правильно ли я тестирую форму в Django?

Всем привет.

Хочу проверить форму, которая на сайте принимает данные, создает новый объект:

Так:

Url:

url(r'^addcreview(?P<add_id>[0-9]+)$', views.addcreview, name='addcreview'),


Модель:

class Creview(models.Model):
    creview = models.ForeignKey(Course, on_delete=models.CASCADE, default=1)
    userview = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
    # username = models.CharField(max_length=200, help_text="Имя автора отзыва", verbose_name="Имя автора отзыва")
    review = models.TextField(help_text="Отзыв", verbose_name="Сам отзыв о курсе")


View:

def addcreview(request, add_id):
    token = {}
    token.update(csrf(request))
    if request.user.is_authenticated():
        current_user = request.user
        if request.POST:
            course = Course.objects.get(id=add_id)
            form = CreviewForm(request.POST)
            if form.is_valid():
                review = form.cleaned_data['review']
                review_obj = Creview(creview=course, userview=current_user, review=review)
                review_obj.save()
                return redirect('/course' + add_id, token)


Тест:

class Test_Forms_For_Safe(TestCase):
    def test_creview_form_save(self):
        ##########
        user = User.objects.create(id=1, username="gavgav", password='W123456')
        profile = Profile.objects.create(user=user)
        self.client.login(username='gavgav', password='W123456')
        ##########
        course = Course.objects.create(id=1, title="заголовок")
        ##########
        response = self.client.post('/addcreview1',
                                    {'id': "1", "creview": "course", "userview": "user", "review": "ревьюшка"})
        ##########

        creview = Creview.objects.get(id=1)

        self.assertEqual(creview.review, 'ревьюшка')


Т.е. моя Логика:

- создаю юзера
- захожу с ним на сайт
- создаю объект Course
- передаю в url post данные, которые должны создать объект Creview
- Проверяю совпадение данных.

Ошибка:

faceset.models.DoesNotExist: Creview matching query does not exist.


Можете подсказать, что я делаю не так?
  • Вопрос задан
  • 590 просмотров
Решения вопроса 3
@SkiBY
Неправильно.

1. Проверку на аутентифицацию делать принято как
@login_required
def...

это удобно - сразу обрабатывается ситуация с перенаправлением на страницу логина и т.д.

2. Сначала нужно создать объект. Обработка формы стандартным методом для POST:

form = CreviewForm(request.POST or None)
if request.method == 'POST' and form.is_valid():
        obj = form.save(commit=False)
        obj.course = course
        ....
        obj.save()
        form.save() 
else:
    возврат к представлению для исправления данных и т.д.


Этот формат сам проверит и csrf, и данные в форме, и прочая-прочая
Ответ написан
@deliro
Правильнее будет спросить, что ты делаешь так.
1) Модель построена ужасно. on_delete=models.CASCADE - дефолтное поведение связей при удалении, не понимаю, зачем его указывать. default=1 - это какой-то костыль, который накроется медным тазом в самый неподходящий момент. Про имена атрибутов я уже молчу.

2) Твоя вьюха не выдерживает ничего, кроме правильных данных. Что будет, если юзер не авторизован? Что будет, если пришёл GET запрос (или любой другой не POST)? Что будет, если форма невалидна? Тесты не фейлятся в этих случаях (так как их нет, хахаха) - значит ты тестируешь не так.

3) Юзера создавать нужно методом create_user, сейчас ты создаёшь юзера, забивая ему в БД хэш пароля, равный W123456. Конечно, не при каких обстоятельствах ты не залогинишься под этим юзером. Следовательно, весь остальной тест фейлится. Автоинкрементный ID явно указывать нельзя, за исключением тех случаев, когда ты бэкап БД накатываешь на чистую БД. Вот так creview = Creview.objects.get(id=1) тоже не делай. У тебя тест создаёт ровно один объект Creview, получить ты его можешь, например, вот так: Creview.objects.first()
Ответ написан
@ivlevdenis_ru
python, django, celery, redis, kivy, git
response = self.client.post('/addcreview1',
                                    {'id': "1", "creview": "course", "userview": "user", "review": "ревьюшка"})

В поле creview передается строка, а нужно число.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы