Lesson 19 - User Authentication
LEARN
User Authentication
- User authentication is hard to get right
- Django provides powerful built-in tools
- We extend the Django implementation
User Object
- username
- password
- first_name
- last_name
Forms and Logic
- Log in
- Log out
- Sign up
- User status
Log In
config/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('',
TemplateView.as_view(template_name="templates/theme.html"),
name='home'),
]
config/settings.py
LOGIN_REDIRECT_URL = 'home'
templates/registration/login.html
{% extends 'theme.html' %}
{% block content %}
<h2>Log In</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Log In</button>
</form>
{% endblock content %}
User status
templates/theme.html
{% if user.is_authenticated %}
<p>Hi {{ user.username }}!</p>
<p><a href="{% url 'logout' %}">Log out</a></p>
{% else %}
<p>You are not logged in.</p>
<a href="{% url 'login' %}">Log In</a>
{% endif %}
Home Page
templates/theme.html
<html>
<head>
<title>User Authentication Demo</title>
<link href="/static/css/base.css" rel="stylesheet"s>
</head>
<body>
<header>
<h1><a href="{% url 'home' %}">Home Page</a></h1>
{% if user.is_authenticated %}
<p>Hi {{ user.username }}!</p>
<p><a href="{% url 'logout' %}">Log out</a></p>
{% else %}
<p>You are not logged in.</p>
<a href="{% url 'login' %}">Log In</a>
{% endif %}
</header>
{% block content %}
{% endblock content %}
</body>
</html>
Log out
Follow this link to log out
<a href="{% url 'logout' %}">Log out</a>
config/settings.py
LOGOUT_REDIRECT_URL = 'home'
Sign up
Create a new app
$ python manage.py startapp accounts
config/settings.py
INSTALLED_APPS = [..., 'accounts', ]
config/urls.py
urlpatterns = [
...
path('accounts/', include('accounts.urls')),
...
]
accounts/urls.py
from django.urls import path
from .views import SignUpView
urlpatterns = [
path('signup/', SignUpView.as_view(), name='signup'),
]
accounts/views.py
from django.urls import reverse_lazy
from django.views import generic
class SignUpView(generic.CreateView):
form_class = UserCreationForm
success_url = reverse_lazy('login')
template_name = 'registration/signup.html'
templates/sign_up.html
{% extends 'theme.html' %}
{% block content %}
<h2>Sign Up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign Up</button>
</form>
{% endblock content %}
BUILD
Demo of User Accounts
- Shows how to manage user authentication
- User Accounts
To Do List
- Test
- Accounts CRUD Test
- Accounts Views Test
- Fix
- Extend
- Add Fields to Book
- Extend views to show all fields
- Improve
- Setup command aliases
- Migrate database
- Simplify code
- Use CRUD Test Pattern
- Use Views Test Pattern
Build Users Project
Start Users project
$ cd week7/Users
$ django-admin startproject config .
$ python manage.py startapp accounts
config/settings.py
TEMPLATES = [
{
...
'DIRS': [BASE_DIR / 'templates'],
...
},
]
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / "static"]
ALLOWED_HOSTS = ['markseaman.pythonanywhere.com', '127.0.0.1', 'localhost']
INSTALLED_APPS = [
...
'accounts',
]
Test Admin View
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py createsuperuser
$ python manage.py runserver
$ browse to 127.0.0.1:8000/admin/
$ git add . && git commit -m "Initial Accounts app"
Django Test
accounts/tests.py
class TestAccountsViews(TestCase):
def test_home_view(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'theme.html')
def test_login_view(self):
response = self.client.get('/accounts/login')
self.assertEqual(response.status_code, 301)
self.assertEqual(response.url, '/accounts/login/')
response = self.client.get('/accounts/login/')
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'theme.html')
def test_logout_view(self):
response = self.client.get('/accounts/logout/')
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, '/')
def test_signup_view(self):
response = self.client.get('/signup')
self.assertEqual(response.status_code, 301)
self.assertEqual(response.url, '/signup/')
response = self.client.get('/signup/')
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'theme.html')