Issue with Testing UpdateView in Django

I have an UpdateView that allows editing objects of the Scooter model. After successfully processing the form (via a POST request), the view is supposed to redirect the user to the detail page of the edited scooter (with a 302 status code). However, in my test, I see that the response after the POST request returns a 200 status code, and response.context contains the object data, as if the form was re-rendered instead of a redirect occurring.

Why does the UpdateView return a 200 status code after the POST request, even though the get_success_url method is correctly configured? Is using response.context after POST appropriate in such a test? Should I instead use refresh_from_db for the object in the database? Is there a better way to test UpdateView behavior in Django to avoid potential inconsistencies with the view's behavior after a POST request?

(these are in different files ofc, i just needed to paste it here)

@pytest.mark.django_db
def test_scooter_detail_edit_data(client, superuser_user, available_scooter):
    url = reverse('scooter-update', kwargs={'scooter_id': available_scooter.id})
    client.force_login(superuser_user)
    response = client.get(url)
    assert response.status_code == 200
    assert response.context['scooter'].available == True
    assert response.context['scooter'].daily_price == 100
    response = client.post(url, data={
        'available': False,
        'daily_price': 200,
    })
    assert response.status_code == 200
    assert response.context['scooter'].available == False
    assert response.context['scooter'].daily_price == 200


class ScooterUpdateView(UpdateView):
    model = Scooter
    template_name = 'scooters/scooter_edit.html'
    pk_url_kwarg = 'scooter_id'
    fields = [
        'available',
        'image',
        'daily_price',
        'weekly_price',
        'monthly_price',
        'deposit_amount',
    ]

    def get_queryset(self):
        if self.request.user.is_superuser:
            return Scooter.objects.all()
        raise Http404

    def get_success_url(self):
        return reverse_lazy('scooter-detail', kwargs={'scooter_id': self.object.pk})


@fixture
def available_scooter():
    scooter = Scooter.objects.create(
        brand="Yamaha",
        scooter_model="XMax 300",
        capacity=300,
        year=2022,
        registration_number="KR12345",
        available=True,
        image=None,
        daily_price=100,
        weekly_price=600,
        monthly_price=2000,
        deposit_amount=500,
    )
    return scooter

tests/tests.py::test_scooter_detail_edit_data PASSED

Why does the UpdateView return a 200 status code after the POST request, even though the get_success_url method is correctly configured?

Because the POST request is not a success. Indeed, if the data you submit to the form is invalid, and the form thus rejects the data, the UpdateView will render the template with the form, and the form that shows the errors.

Here it looks like data is missing, some fields might be required, and thus the form probably rejects the data.

Вернуться на верх