En un proyecto de Django, tengo pruebas que verifican que una URL use una vista específica basada en clases. por ejemplo, tengo esta vista:
from django.views.generic import TemplateView class HomeView(TemplateView): template_name = "home.html"Y esta prueba:
from django.test import TestCase from django.urls import resolve from myapp import views class UrlsTestCase(TestCase): def test_home_view(self): self.assertEqual(resolve("/").func.__name__, views.HomeView.__name__)Esta prueba pasa en Django 3.x pero una vez que la pruebo con Django 4.0, la prueba falla con:
self.assertEqual(resolve("/").func.__name__, views.HomeView.__name__) AssertionError: 'view' != 'HomeView' - view + HomeViewObviamente, algo ha cambiado en Django 4.0, pero no puedo ver nada relacionado en las notas de la versión .
Entonces, ¿qué ha cambiado y cómo puedo hacer que esta prueba funcione de nuevo (o cómo puedo probarla de una mejor manera)?
Usa .as_view() , por lo que no devuelve un objeto de clase, sino una función que manejará las solicitudes mediante la creación de una nueva HomeView y activará el método correspondiente basado en el método HTTP.
Puede verificar si es un método de HomeView al verificar el atributo .view_class . Además, probablemente sea mejor verificar si las dos clases son iguales, no los nombres de estas clases:
# ↓ no .__name__ ↓ self.assertEqual(resolve('/').func. view_class , views.HomeView) Investigué un poco por qué comparar los __name__ ya no funciona. Aparentemente, en django-3.0 usaron la update_wrapper(…) que establece el __name__ , __qualname__ , etc. de un objeto (en este caso, la clase) a la función. De hecho, en el código fuente [GitHub] , podemos ver:
@classonlymethod def as_view(cls, **initkwargs): # … def view(request, *args, **kwargs): # … # … # take name and docstring from class update_wrapper( view, cls, updated=() ) # …
esto se ha cambiado en django-4.0 donde también explicaron en un comentario por qué ya no hacen eso [GitHub] :
@classonlymethod def as_view(cls, **initkwargs): # … # __name__ and __qualname__ are intentionally left unchanged as # view_class should be used to robustly determine the name of the view # instead. # …