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.