Set variable in base.html when using LoginView class

I have a base.html file that makes the template of my site, within that template I use a variable to set a message which I want to show in every view (as an example). That work fine if I can render the view within my views.py. But the login page is “rendered” directly from the urls.py file in the users app, using

views.LoginView.as_view

However I want the message to appear even in the login page.

Below are the minimum files to show the problem (all imports are resolved and it works)
base.html with the {{ message }}

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    {% load static %}
</head>
<body>
    <div id="message">
    <p>{{ message }}</p>
    </div>
    {% block content %}
    {% endblock %}   
</body>
</html>

This works fine in my main app of the site where
url.py

urlpatterns = [
    path('', views.index, name='index'),
]

views.py here I set message

def index(request):
    message=”have a nice day today”
    return render(request, 'index.html', {'message': message} )

index.html

{% extends 'base.html' %}
{% block content %}
<div >
    <h2>You're welcome</h2>
</div>
{% endblock %}

Now my login page uses the same base.html and looks something like this

login.html

{% extends 'base.html' %}
{% block content %}
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
    </form>
{% endblock %}

and my users app urls.py

urlpatterns = [
    path('login/', views.LoginView.as_view(template_name="/login.html"), name='login'),
]

Problem is that the message variable isn’t initialized and therefore not shown.
How can I generate the correct LoginView AND set the message variable?

I have tried to make a new class, with only three lines:
views.py

def myloginview(LoginView)
    message=”please login”
    template_name="/login.html"

and the urls.py

urlpatterns = [
    path('login/', views.myloginview, name='login'),
]

as a start (hoping I could set the variable that way) but that gave me an error that no httpResonse or None (*1) was returned.

(*1) sorry forgot the exact error, have set everything back to the original state.

Any ideas? Thanks.

You’re basically thinking in the right direction.

LoginView is a class-based view.

Assuming the LoginView is the class from django.contrib.auth, you can:

  • Subclass that view with your own class
  • Set the extra_context dict with key of “message” and value of your message.
    Note that this is a static setting - you don’t specify if the message changes at any time.
    If you need a more dynamic environment, you might want to override get_context_data.
  • Set your URL to point to your class.

Thanks, I did try that but I got an error.
I tried again with the following to setup a basic structure, so without passing the message variable to have that working first.

views.py

from django.shortcuts import render
from django.contrib.auth import views

def myloginview(LoginView):
    template_name="/login.html"

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('login/', views.myloginview, name='login'),
]

But the error I get is:

ValueError at /users/login/

The view users.views.myloginview didn’t return an HttpResponse object. It returned None instead.

Request Method: GET
Request URL: http://127.0.0.1:8000/users/login/
Django Version: 3.1.5
Exception Type: ValueError
Exception Value: The view users.views.myloginview didn’t return an HttpResponse object. It returned None instead.
Exception Location: venv/lib/python3.9/site-packages/django/core/handlers/base.py, line 309, in check_response
Python Executable: venv/bin/python
Python Version: 3.9.1
Python Path: [’/my_project_path/app’, ‘/usr/lib/python39.zip’, ‘/usr/lib/python3.9’, ‘/usr/lib/python3.9/lib-dynload’, ‘venv/lib/python3.9/site-packages’]
Server time: Tue, 05 Jan 2021 11:41:05 +0000

How do I debug this?
Looking at the LoginView class overwriting the template_name should be all I have to do.
What am I missing?

You have at least two errors in what you’ve posted.

  1. When you define a class, you need to use the class keyword, not def.

  2. Notice the path definition when you’re using a CBV:

path('login/', views.LoginView.as_view(template_name="/login.html"), name='login'),

See Class Based Views for more information

Thanks that boosted my confidence, tried so hard not to show this is my first Django project :slight_smile:
But you are right there was one more thing I needed to do.
For everyone looking for an answer to this question, this works for me:

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('login/', views.myloginview.as_view(), name='login'),
]

views.py

from django.contrib.auth import views as auth_views

class myloginview(auth_views.LoginView):
    template_name="/login.html"
    extra_context = {'message': 'Please login here'}

Thanks for your help!

I apologize for the way that was worded - in retrospect that reads far more harshly than intended.
What I was really trying to convey was that fixing those two items might not have been enough to resolve the issue, and that further work may have been necessary to make this functional.
Anyway, I’m glad to see you’ve got it working!

No worries, I read it as you intended.