SecNot

ene 01, 2015

Formulario Login usando Class Based Views

Recientemente he tenido que crear un panel de control para una aplicación django, su función era mostrar estadísticas de los pedidos. Como en casi todos los casos el primer problema fue crear un sistema de login, esta es una situación muy común que se presenta en la mayoría de aplicaciones, la diferencia es que en este caso me decidí por usar Class Based Views, y me he quedado sorprendido con la simplicidad y limpieza del código:

# views.py

from django.views.generic import FormView, TemplateView, RedirectView

# Authentication imports
from django.contrib.auth import login, logout
from django.contrib.auth.forms import AuthenticationForm

from django.core.urlresolvers import reverse_lazy

from cesta.models import Pedido



class LoginView(FormView):
    form_class = AuthenticationForm
    template_name = "control_panel/login.html"
    success_url =  reverse_lazy("panel-dashboard")

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated():
            return HttpResponseRedirect(self.get_success_url())
        else:
            return super(LoginView, self).dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        login(self.request, form.get_user())
        return super(LoginView, self).form_valid(form)


class LogoutView(RedirectView):
    pattern_name = 'panel-login'

    def get(self, request, *args, **kwargs):
        logout(request)
        return super(LogoutView, self).get(request, *args, **kwargs)


class LoginRequiredMixin(object):

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated():
            return HttpResponseRedirect(reverse('panel-login'))
        else:
            return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)


class ControlPanelView(LoginRequiredMixin, TemplateView):
    template_name = 'control_panel/panel.html'

    def get_context_data(self, **kwargs):
        context = super(ControlPanelView, self).get_context_data(**kwargs)
        context['pedidos_pendientes'] = Pedido.objects.pendientes()
        # ....
        # Recopilar resto de la informacion
        # ....

        return context

Descargar views.py

# urls.py

from django.conf.urls import patterns, url
from .views import ControlPanelView, LoginView, LogoutView

urlpatterns = patterns('',
    url(
        regex = r'^$',
        view  = ControlPanelView.as_view(),
        name  = "panel-dashboard"),
    url(
        regex = r'^login/$',
        view  = LoginView.as_view(),
        name  = "panel-login"),
    url(
        regex = r'^logout/$',
        view  = LogoutView.as_view(),
        name  = "panel-logout"),
)

Descargar urls.py

Por último un ejemplo para el template login.html:

{% extends 'base.html' %}

{% block content %}
<div class="login-panel">
        <form method="post" role="form">{% csrf_token %}
                {{ form.username }}
                {{ form.password }}
                <input type="submit" value="Login"/>
        </form>
</div>
{% endblock %}