3
\$\begingroup\$

I am trying to fight my way trough self learning Django (as this is a beast on its own) and Python (just for coding <3) in combination with nginx, PostgreSQL and gunicorn - I have some limited experience with PHP.

After a short struggle I managed to get everything up and running (enough tutorials for that around).

Basically what I am doing right now is trying to customize the Django authentication system, specifically starting with the login part and adding a "remember me" option for the user, I got everything to work the way I like, but I am wondering if I am doing everything the 'correct' (or convenient) way? (I started with customizing the user model, so you might encounter some bits and pieces related to that.) So I could use some pointers of what I can do better or improve.

In my project directory:

settings.py

SESSION_EXPIRE_AT_BROWSER_CLOSE = True

I added the above line so that any sessions that are created are expired on browser close by default (yes, this might not always work in Chrome).

In my APP directory for the user authentication:

forms.py

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

class CustomAuthenticationForm(AuthenticationForm):
    username = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Username','required': True,'autofocus' : True}))
    password = forms.CharField(widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Password','required': True}))
    remember_me = forms.BooleanField(required=False)

As you can see I am using bootstrap classes to style the input fields.

view.py

from django.shortcuts import render

# Create your views here.

from django.urls import reverse_lazy
from django.contrib.auth.views import LoginView
from django.contrib.auth import login

from .forms import CustomAuthenticationForm

class Login(LoginView):

    authentication_form = CustomAuthenticationForm

    form_class = CustomAuthenticationForm

    template_name = 'login.html'

    def form_valid(self, form):

        remember_me = form.cleaned_data['remember_me']

        login(self.request, form.get_user())

        if remember_me:

            self.request.session.set_expiry(1209600)

        return super(LoginView, self).form_valid(form)

To make the "remember me" option work I am trying to read out the "remember_me" checkbox for the template that has been posted in the form. Based on if it's set or not, it sets the session expiry to two weeks.

This is how my urls.py looks like in my 'users' APP:

urls.py

from django.urls import path
from . import views
from .forms import CustomAuthenticationForm

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

The most ugliest and least django/python-fied must be my templates (e. g. the labels, as I tried to avoid using the full form 'generation'). I am absolutely sure this and the forms.py can be improved a lot.

The two templates:

base.html

<!doctype html>

<html lang="en">
  
  <head>

    <meta charset="utf-8">
    
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">

	{% block head %}

	{% load static %}

        <link rel="stylesheet" href="{% static '/main/css/style.css' %}" type="text/css">	

        <title>My Python Website</title>

	{% endblock %}
  
  </head>
  
    <body>

	{% block body %}
	
	{% endblock %}

	<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    
	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

  </body>

</html>

Here I load the bootstrap CSS/JS files and a custom CSS file:

login.html

{% extends 'base.html' %}

{% block head %}

{% load static %}

    <link rel="stylesheet" href="{% static '/users/css/style.css' %}" type="text/css">	

    <title>My Python Login</title>

{% endblock %}


{% block body %}

<div class="container text-center">

    <form class="form-signin" method="post" action="{% url 'login' %}"> 

	{% csrf_token %}

        <img class="mb-4" src="{% static 'main/images/placeholder_logo.png' %}" width="114" height="100" alt="">

        <h1 class="h3 mb-3 font-weight-normal">Please Sign in</h1>

        <label for="id_username" class="sr-only">Username</label>

        {{ form.username }}

        <label for="id_password" class="sr-only">Password</label>

        {{ form.password }}

        <div class="checkbox mb-3">
      
          <label for="id_remember_me">

              {{ form.remember_me }} Remember me

          </label>

      </div>

        {% if form.errors %}
        
        <p  class="alert alert-danger" role="alert">
           
            Your username and password didn't match.
            Please try again.

        </p>
        
        {% endif %}

        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>

        <p class="mt-5 mb-3 text-muted">&copy; My First Python Website 2017-2018</p>

    </form>

</div>

{% endblock %}

So now, how does this look like? Things that confuse me at the moment if for example the CSS styling approach of the templates and the forms. As half of the class/id assigning is happening in the templates and the other half in the forms.py. How can I improve upon this and what is the general way of working or the recommended way of doing this?

\$\endgroup\$
2
\$\begingroup\$

In your forms.py, widget attr common class form-control added for username, and password.

If you are confirm that all of your form class have same name like all of my field have form-control class then you can use it on your template not in forms.py.

Think a case, you have username, gender, aboutme field. Suppose username required form-control class, gender requred checkbox-inline class, and aboutme requried form-control-lg class. Then you should add this on your forms.py widget attr.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.