├── README.md ├── accounts ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── admin.cpython-36.pyc │ ├── forms.cpython-36.pyc │ ├── models.cpython-36.pyc │ └── views.cpython-36.pyc ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── __init__.py │ └── __pycache__ │ │ └── __init__.cpython-36.pyc ├── models.py ├── tests.py └── views.py ├── db.sqlite3 ├── djusers ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── settings.cpython-36.pyc │ ├── urls.cpython-36.pyc │ ├── views.cpython-36.pyc │ └── wsgi.cpython-36.pyc ├── settings.py ├── urls.py ├── views.py └── wsgi.py ├── handling_auth.png ├── manage.py ├── requirements.txt └── templates ├── home.html ├── login.html └── signup.html /README.md: -------------------------------------------------------------------------------- 1 |

2 |

3 | 4 | JustDjango 5 | 6 |

7 |

8 | The Definitive Django Learning Platform. 9 |

10 |

11 | 12 | # Handling User Authentication 13 | 14 | A basic introduction to handling user authentication in Django without any 3rd party libraries. 15 | 16 |

17 | 18 |

19 | 20 | --- 21 | 22 |
23 | 24 | Other places you can find us:
25 | 26 | YouTube 27 | Twitter 28 | 29 |
30 | -------------------------------------------------------------------------------- /accounts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/accounts/__init__.py -------------------------------------------------------------------------------- /accounts/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/accounts/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/accounts/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/forms.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/accounts/__pycache__/forms.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/accounts/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/accounts/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /accounts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountsConfig(AppConfig): 5 | name = 'accounts' 6 | -------------------------------------------------------------------------------- /accounts/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth import ( 3 | authenticate, 4 | get_user_model 5 | 6 | ) 7 | 8 | User = get_user_model() 9 | 10 | 11 | class UserLoginForm(forms.Form): 12 | username = forms.CharField() 13 | password = forms.CharField(widget=forms.PasswordInput) 14 | 15 | def clean(self, *args, **kwargs): 16 | username = self.cleaned_data.get('username') 17 | password = self.cleaned_data.get('password') 18 | 19 | if username and password: 20 | user = authenticate(username=username, password=password) 21 | if not user: 22 | raise forms.ValidationError('This user does not exist') 23 | if not user.check_password(password): 24 | raise forms.ValidationError('Incorrect password') 25 | if not user.is_active: 26 | raise forms.ValidationError('This user is not active') 27 | return super(UserLoginForm, self).clean(*args, **kwargs) 28 | 29 | 30 | class UserRegisterForm(forms.ModelForm): 31 | email = forms.EmailField(label='Email address') 32 | email2 = forms.EmailField(label='Confirm Email') 33 | password = forms.CharField(widget=forms.PasswordInput) 34 | 35 | class Meta: 36 | model = User 37 | fields = [ 38 | 'username', 39 | 'email', 40 | 'email2', 41 | 'password' 42 | ] 43 | 44 | def clean(self, *args, **kwargs): 45 | email = self.cleaned_data.get('email') 46 | email2 = self.cleaned_data.get('email2') 47 | if email != email2: 48 | raise forms.ValidationError("Emails must match") 49 | email_qs = User.objects.filter(email=email) 50 | if email_qs.exists(): 51 | raise forms.ValidationError( 52 | "This email has already been registered") 53 | return super(UserRegisterForm, self).clean(*args, **kwargs) 54 | -------------------------------------------------------------------------------- /accounts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/accounts/migrations/__init__.py -------------------------------------------------------------------------------- /accounts/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/accounts/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /accounts/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | 3 | from django.contrib.auth import ( 4 | authenticate, 5 | get_user_model, 6 | login, 7 | logout 8 | ) 9 | 10 | from .forms import UserLoginForm, UserRegisterForm 11 | 12 | 13 | def login_view(request): 14 | next = request.GET.get('next') 15 | form = UserLoginForm(request.POST or None) 16 | if form.is_valid(): 17 | username = form.cleaned_data.get('username') 18 | password = form.cleaned_data.get('password') 19 | user = authenticate(username=username, password=password) 20 | login(request, user) 21 | if next: 22 | return redirect(next) 23 | return redirect('/') 24 | 25 | context = { 26 | 'form': form, 27 | } 28 | return render(request, "login.html", context) 29 | 30 | 31 | def register_view(request): 32 | next = request.GET.get('next') 33 | form = UserRegisterForm(request.POST or None) 34 | if form.is_valid(): 35 | user = form.save(commit=False) 36 | password = form.cleaned_data.get('password') 37 | user.set_password(password) 38 | user.save() 39 | new_user = authenticate(username=user.username, password=password) 40 | login(request, new_user) 41 | if next: 42 | return redirect(next) 43 | return redirect('/') 44 | 45 | context = { 46 | 'form': form, 47 | } 48 | return render(request, "signup.html", context) 49 | 50 | 51 | def logout_view(request): 52 | logout(request) 53 | return redirect('/') 54 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/db.sqlite3 -------------------------------------------------------------------------------- /djusers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/djusers/__init__.py -------------------------------------------------------------------------------- /djusers/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/djusers/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /djusers/__pycache__/settings.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/djusers/__pycache__/settings.cpython-36.pyc -------------------------------------------------------------------------------- /djusers/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/djusers/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /djusers/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/djusers/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /djusers/__pycache__/wsgi.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/djusers/__pycache__/wsgi.cpython-36.pyc -------------------------------------------------------------------------------- /djusers/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 4 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 | 6 | 7 | # Quick-start development settings - unsuitable for production 8 | # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ 9 | 10 | # SECURITY WARNING: keep the secret key used in production secret! 11 | SECRET_KEY = '5%!mbw_wxuyyy7^7)-4io*zwb1m(!wvub_5vo8yg=m2g-0n8g+' 12 | 13 | # SECURITY WARNING: don't run with debug turned on in production! 14 | DEBUG = True 15 | 16 | ALLOWED_HOSTS = [] 17 | 18 | 19 | # Application definition 20 | 21 | INSTALLED_APPS = [ 22 | 'django.contrib.admin', 23 | 'django.contrib.auth', 24 | 'django.contrib.contenttypes', 25 | 'django.contrib.sessions', 26 | 'django.contrib.messages', 27 | 'django.contrib.staticfiles', 28 | 29 | 'accounts' 30 | ] 31 | 32 | MIDDLEWARE = [ 33 | 'django.middleware.security.SecurityMiddleware', 34 | 'django.contrib.sessions.middleware.SessionMiddleware', 35 | 'django.middleware.common.CommonMiddleware', 36 | 'django.middleware.csrf.CsrfViewMiddleware', 37 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 38 | 'django.contrib.messages.middleware.MessageMiddleware', 39 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 40 | ] 41 | 42 | ROOT_URLCONF = 'djusers.urls' 43 | 44 | TEMPLATES = [ 45 | { 46 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 47 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 48 | 'APP_DIRS': True, 49 | 'OPTIONS': { 50 | 'context_processors': [ 51 | 'django.template.context_processors.debug', 52 | 'django.template.context_processors.request', 53 | 'django.contrib.auth.context_processors.auth', 54 | 'django.contrib.messages.context_processors.messages', 55 | ], 56 | }, 57 | }, 58 | ] 59 | 60 | WSGI_APPLICATION = 'djusers.wsgi.application' 61 | 62 | 63 | # Database 64 | # https://docs.djangoproject.com/en/2.1/ref/settings/#databases 65 | 66 | DATABASES = { 67 | 'default': { 68 | 'ENGINE': 'django.db.backends.sqlite3', 69 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 70 | } 71 | } 72 | 73 | 74 | # Password validation 75 | # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators 76 | 77 | AUTH_PASSWORD_VALIDATORS = [ 78 | { 79 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 80 | }, 81 | { 82 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 83 | }, 84 | { 85 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 86 | }, 87 | { 88 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 89 | }, 90 | ] 91 | 92 | 93 | # Internationalization 94 | # https://docs.djangoproject.com/en/2.1/topics/i18n/ 95 | 96 | LANGUAGE_CODE = 'en-us' 97 | 98 | TIME_ZONE = 'UTC' 99 | 100 | USE_I18N = True 101 | 102 | USE_L10N = True 103 | 104 | USE_TZ = True 105 | 106 | 107 | # Static files (CSS, JavaScript, Images) 108 | # https://docs.djangoproject.com/en/2.1/howto/static-files/ 109 | 110 | STATIC_URL = '/static/' 111 | -------------------------------------------------------------------------------- /djusers/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path 3 | 4 | from .views import home 5 | 6 | from accounts.views import login_view, register_view, logout_view 7 | 8 | urlpatterns = [ 9 | path('admin/', admin.site.urls), 10 | path('', home), 11 | path('accounts/login/', login_view), 12 | path('accounts/register/', register_view), 13 | path('accounts/logout/', logout_view) 14 | ] 15 | -------------------------------------------------------------------------------- /djusers/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.contrib.auth.decorators import login_required 3 | 4 | 5 | @login_required 6 | def home(request): 7 | return render(request, "home.html", {}) 8 | -------------------------------------------------------------------------------- /djusers/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for djusers project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djusers.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /handling_auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justdjango/Handling-User-Auth/29937e646b316c32d9b2144489c5c487390a85b8/handling_auth.png -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == '__main__': 6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djusers.settings') 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError as exc: 10 | raise ImportError( 11 | "Couldn't import Django. Are you sure it's installed and " 12 | "available on your PYTHONPATH environment variable? Did you " 13 | "forget to activate a virtual environment?" 14 | ) from exc 15 | execute_from_command_line(sys.argv) 16 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==2.1.5 2 | pytz==2018.5 3 | -------------------------------------------------------------------------------- /templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 |

This is the home page

13 | 14 | 15 | -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 |

Login

13 |
14 | {% csrf_token %} 15 | {{ form }} 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /templates/signup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 |
13 | {% csrf_token %} 14 | {{ form }} 15 | 16 |
17 | 18 | 19 | --------------------------------------------------------------------------------