Django中reverse()与reverse_lazy()的差异及FBV/CBV调用疑问
reverse() Works in FBVs but Not CBVs (When Importing Views in urls.py) Great question! This trips up so many Django developers at first, and it all comes down to when your code actually runs during Django's startup and request lifecycle. Let's break this down clearly:
1. The Core Difference: Execution Timing
Function-Based Views (FBVs): When you import an FBV in
urls.py, you're only loading the function definition into memory. The code inside the function (including anyreverse()calls) doesn't execute until a user sends a request to that URL. By that point, Django has fully parsed and registered all yoururlpatterns, soreverse()can easily find the URL name it needs.Example of a safe FBV:
# views.py from django.shortcuts import reverse, render def my_fbv(request): # This line only runs when a request hits the view profile_url = reverse('user-profile') return render(request, 'home.html', {'profile_url': profile_url})Class-Based Views (CBVs): CBVs are classes, and any code assigned to class-level attributes runs as soon as the class is imported (during Django's startup), not when a request comes in. If you use
reverse()directly for attributes likesuccess_url, this code tries to resolve the URL beforeurlpatternshave been fully processed by Django's URL resolver—hence the error.Example of a problematic CBV:
# views.py (THIS WILL FAIL) from django.views.generic import RedirectView from django.shortcuts import reverse class MyCBV(RedirectView): # This line runs during startup, before URLs are ready url = reverse('user-profile') # Error: URL name not found!
2. How reverse_lazy() Fixes This
reverse_lazy() is a lazy-evaluated version of reverse()—it doesn't compute the actual URL string until the value is actually needed. For CBV class attributes, that means the URL lookup happens when Django processes a request (after urlpatterns are fully loaded), just like it does in FBVs.
Fixed CBV using reverse_lazy():
# views.py (WORKS!) from django.views.generic import RedirectView from django.urls import reverse_lazy class MyCBV(RedirectView): # This is a lazy object; URL lookup happens later url = reverse_lazy('user-profile')
3. Exception: reverse() Works in CBV Methods!
You don't need reverse_lazy() everywhere in a CBV—only for class-level attributes. If you call reverse() inside a method like get() or post(), that code runs when a request is processed (same timing as FBVs), so reverse() works perfectly:
from django.views.generic import TemplateView from django.shortcuts import reverse class MyCBV(TemplateView): template_name = 'dashboard.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # This runs during request processing—URLs are fully ready context['settings_url'] = reverse('user-settings') return context
4. Why Importing Views in urls.py Doesn't Break FBVs
Even though urlpatterns haven't been fully parsed when you import your views in urls.py, FBVs don't execute their internal code until a request arrives. The function definition is just stored in memory, and the reverse() call inside waits until the URL resolver is completely set up.
内容的提问来源于stack exchange,提问作者RyuCoder

