Reputation: 1586
I'd like to add one line to the LoginView that comes with django. I know how to do this via subclassing, but I have a feeling that I don't need to replicate all of the code in the view that I want to subclass.
The only line that I've added is the second last line in this view. 100% of the rest of the code in this view is identical to the django vanilla LoginView.
What is the most efficient way to subclass this view and add this one line of code?
class CustomLoginView(LoginView):
"""
Display the login form and handle the login action.
"""
form_class = AuthenticationForm
authentication_form = None
redirect_field_name = REDIRECT_FIELD_NAME
template_name = 'registration/login.html'
redirect_authenticated_user = False
extra_context = None
@method_decorator(sensitive_post_parameters())
@method_decorator(csrf_protect)
@method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
if self.redirect_authenticated_user and self.request.user.is_authenticated:
redirect_to = self.get_success_url()
if redirect_to == self.request.path:
raise ValueError(
"Redirection loop for authenticated user detected. Check that "
"your LOGIN_REDIRECT_URL doesn't point to a login page."
)
return HttpResponseRedirect(redirect_to)
return super().dispatch(request, *args, **kwargs)
def get_success_url(self):
url = self.get_redirect_url()
return url or resolve_url(settings.LOGIN_REDIRECT_URL)
def get_redirect_url(self):
"""Return the user-originating redirect URL if it's safe."""
redirect_to = self.request.POST.get(
self.redirect_field_name,
self.request.GET.get(self.redirect_field_name, '')
)
url_is_safe = url_has_allowed_host_and_scheme(
url=redirect_to,
allowed_hosts=self.get_success_url_allowed_hosts(),
require_https=self.request.is_secure(),
)
return redirect_to if url_is_safe else ''
def get_form_class(self):
return self.authentication_form or self.form_class
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['request'] = self.request
return kwargs
def form_valid(self, form):
"""Security check complete. Log the user in."""
auth_login(self.request, form.get_user())
return HttpResponseRedirect(self.get_success_url())
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
current_site = get_current_site(self.request)
context.update({
self.redirect_field_name: self.get_redirect_url(),
'site': current_site,
'site_name': current_site.name,
**(self.extra_context or {})
})
context.update(csrf(self.request)) #this is the only line that I've added to the vanilla LoginView
return context
Upvotes: 0
Views: 104
Reputation: 313
You don't have to override every method of the class in order to subclass it. It is enough to override the get_context_data
method if you are going to alter that method only. You need to call super().get_context_data(**kwargs)
in order to execute whatever LoginView
class is doing within that method and then just add your line of code like this:
class CustomLoginView(LoginView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update(csrf(self.request))
return context
Upvotes: 1