homepage login form Django

65,546

Solution 1

If you just want to have a homepage with static content that handles logins, the Django built-in auth application can handle this with very little effort. You just need to bind a URL to django.contrib.auth.views.login and probably one to django.contrib.auth.views.logout, write a login template and a post-logout template, then set a couple of setting variables.

The full setup is documented here: https://docs.djangoproject.com/en/dev/topics/auth/default/#module-django.contrib.auth.views

Here are the relevant bits from a working project of mine:

urls.py

# HomeView is a simple TemplateView that displays post-login options
urlpatterns = patterns('',
    ...
    url(r'^myapp/$', HomeView.as_view(template_name='home.html'), name='home'),
    url(r'^accounts/login/$', 'django.contrib.auth.views.login', name='login'),
    url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', name='logout'),
    ...
)

settings.py

from django.core.urlresolvers import reverse_lazy
...
LOGIN_URL = reverse_lazy('login')
LOGIN_REDIRECT_URL = reverse_lazy('home')

login.html

{% extends "base.html" %}

{% block head %}
  <title>Login</title>
{% endblock %}

{% block body %}
  {% if form.errors %}
    <p>Your username and password didn't match. Please try again.</p>
  {% endif %}

  <form method="post" action="{% url 'django.contrib.auth.views.login' %}">
    {% csrf_token %}
    <table>
      <tr>
        <td>{{ form.username.label_tag }}</td>
        <td>{{ form.username }}</td>
      </tr>
      <tr>
        <td>{{ form.password.label_tag }}</td>
        <td>{{ form.password }}</td>
      </tr>
    </table>

    <input type="submit" value="login" />
    <input type="hidden" name="next" value="{{ next }}" />
  </form>
{% endblock %}

logged_out.html

{% extends "base.html" %}

{% block head %}
  <title>Logged out</title>
{% endblock %}

{% block body %}
  <p>You have been logged out.  You may <a href="{% url 'login' %}">log back in</a>.</p>
{% endblock %}

I'm not showing my base.html template but I trust the pattern is obvious. If you want more than a bare login form there's no reason your login.html template couldn't be fancier. The names are default values, as documented for the views, but you could use other choices if you wanted to.

That's all you need for the basic behavior. If you wrap your views with the login_required decorator as described in the docs, it will redirect to your login page any time a non-authenticated user tries to access one of your views. Or, if you're using class-based views, use @method_decorator(login_required) as documented here. Two more snippets from my project:

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator

class HomeView(TemplateView):
    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(HomeView, self).dispatch(*args, **kwargs)

@login_required
def report_for_group(request, group_id):
     ...

The docs include discussions of some more complicated setups, should you need them.

Solution 2

I recommend django-registration it is quite easy. there is an email verification too in it.

you need an addition url say home:

url(r'^home/$', 'photoblog.views.home',name='home'),
.............

its views, home access was limited to only logged-in users

from django.contrib.auth.decorators import login_required
@login_required(login_url='/') #if not logged in redirect to /
def home(request):        
    return render(request, 'home.html')

you don't need csrf in login.py

ie:

def login(request):
    return render(request, 'login.html')

is enough, as render will pass csrf token.

from django.core.urlresolvers import reverse
def auth_view(request):
    username = request.POST.get('username', '')
    password = request.POST.get('password', '')
    user = auth.authenticate(username = username, password = password)      

    if user is not None:
        auth.login(request, user)
        return HttpResponseRedirect(reverse('home'))
    else:
        return HttpResponseRedirect('/accounts/invalid')

Solution 3

You can use Django's built in log in form. It is quit easy and efficient.And it will give you some features like form validation check.

in urls.py:

url(r'^login/$',views.loginView,name='login'),  

in views.py:

from django.contrib.auth import login
from django.contrib.auth.forms import AuthenticationForm


def loginView(request):
    if request.method == 'POST':
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            user = form.get_user()
            login(request, user)
            return redirect('/website/profile/')
    else:
        form = AuthenticationForm()
    return render(request, 'website/login.html', {'form': form})

in html page:

<form method="post">
{% csrf_token %}
{{form.as_p}}
<p><input type="submit" value="Log in"></input></p>

Solution 4

Using Django 1.11. I had the same problem just now, here's what worked for me...

Import the login view class from the built in auth app and pass in your template file via the template_name kwarg.

In urls.py:

from django.contrib.auth.views import LoginView

app_name = 'yourapp'
urlpatterns = [
    url(r'^$', LoginView.as_view(template_name='yourapp/index.html'), name="index"),
]

And in your view you can use the form variable to render out your form. In my case I use bootstrap so.

In index.html:

{% extends 'base.html' %}
{% loads bootstrap %}
{% block content %}
    <form method="post" action="{% url 'login' %}">
        {% csrf_token %}
        {% bootstrap_form form %}
        {% bootstrap_button "Login" button_type="submit" button_class="btn-primary" %}
        {# Assumes you setup the password_reset view in your URLconf #}
        <p><a href="{% url 'password_reset' %}">Lost password?</a></p>
    </form>
{% endblock content %}
Share:
65,546

Related videos on Youtube

Liondancer
Author by

Liondancer

Just trying to get better at programming! Any helpful tips are much appreciated! =D

Updated on February 12, 2020

Comments

  • Liondancer
    Liondancer about 4 years

    I want to create a homepage with a header that asks to login with username/password and a login button to login. Currently, how I have my page set up is that pressing login will send me to a login page. I want to simply enter in the information and press "login" to login on the homepage of my site. How can I design my urls.py and views.py to perform login on the homepage?

    I have a base.html that is the template for my main page. Within the template, I made a login.html partial view:

    <form action='/accounts/auth/' method='POST'> {% csrf_token %}
        <div >
            <label for='username'> Username </label>
            <input type='text' name='Username' id='username'>
            <label for='password'>Password </label>
            <input type='password' name='Password' id='password'>
            <input type='submit' value='login'>
        </div>
    </form>
    

    I am a bit confused for the action attribute as I'm not sure where to send that form data if I wanted to authorize login on the same page.

    My views.py

    def login(request):
        c = {}
        c.update(csrf(request))
        return render(request, 'login.html', c)
    
    
    def auth_view(request):
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = auth.authenticate(username = username, password = password)      
    
        if user is not None:
            auth.login(request, user)
            return HttpResponseRedirect('/accounts/loggedin')
        else:
            return HttpResponseRedirect('/accounts/invalid')
    

    I'm not sure where to HttpResponseRedirect as well if logging in is all done on the home page.

    Perhaps I can do a render(request,SomePartialView.html) instead of HttpResponseRedirect.

    Here is my urls.py:

    url(r'^$', 'photoblog.views.login'),   #displays login.html
    url(r'^accounts/auth/$', 'photoblog.views.auth_view'),    #authorize login
    
  • Michelle Glauser
    Michelle Glauser about 10 years
    I've tried following your advice, but I keep getting "HomeView" not defined. I tried importing to the URLs, but that didn't work. What am I missing?
  • Peter DeGlopper
    Peter DeGlopper about 10 years
    @MichelleGlauser - importing should be all that's necessary. All I can recommend from afar is to check for typos and incorrect paths.
  • ss7
    ss7 almost 9 years
    How can I change the default template location for login? I don't see where to put template_name
  • Peter DeGlopper
    Peter DeGlopper almost 9 years
    @shenk - specify the template_name argument in urls.py, as I did for my home view in the example above.
  • ss7
    ss7 almost 9 years
    Yes but how do you do that with the built in login template? since we are not calling as_view(). I was able to just copy the entire view over and change it that way but that isn't the preferred method obviously.
  • Peter DeGlopper
    Peter DeGlopper almost 9 years
    See the example in the docs I linked to in my answer: url(r'^accounts/login/$', auth_views.login, {'template_name': 'myapp/login.html'}),
  • ss7
    ss7 almost 9 years
    Thanks big help. How can I change the value of {{ next }} right now it isn't showing up as anything?
  • Daniel
    Daniel over 6 years
    You can't add context to it tho, I think.
  • Goran
    Goran over 6 years
    @Daniel, you could try subclassing the LoginView and overriding the get_context_data method.
  • Andy Clifton
    Andy Clifton almost 4 years
    Don't forget to close out the form using a </form> tag