├── .gitignore ├── accounts ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py ├── config ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── manage.py ├── requirements.txt └── templates ├── base.html ├── home.html └── registration ├── login.html ├── password_change_done.html ├── password_change_form.html ├── password_reset_complete.html ├── password_reset_confirm.html ├── password_reset_done.html ├── password_reset_email.html ├── password_reset_form.html ├── password_reset_subject.txt └── signup.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # macOS + PyCharm 107 | .DS_Store 108 | .idea/ 109 | -------------------------------------------------------------------------------- /accounts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akiyoko/django-auth-sample/d976650d484ed6b2dc743ba25b973f9ad5429523/accounts/__init__.py -------------------------------------------------------------------------------- /accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth.admin import UserAdmin 3 | 4 | from .models import CustomUser 5 | 6 | 7 | class CustomUserAdmin(UserAdmin): 8 | pass 9 | 10 | 11 | admin.site.register(CustomUser, CustomUserAdmin) 12 | -------------------------------------------------------------------------------- /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.contrib.auth.forms import UserCreationForm 2 | 3 | from .models import CustomUser 4 | 5 | 6 | class SignupForm(UserCreationForm): 7 | class Meta(UserCreationForm.Meta): 8 | model = CustomUser 9 | fields = ('username', 'email') -------------------------------------------------------------------------------- /accounts/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.1 on 2018-09-21 16:35 2 | 3 | import django.contrib.auth.models 4 | import django.contrib.auth.validators 5 | from django.db import migrations, models 6 | import django.utils.timezone 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ('auth', '0009_alter_user_last_name_max_length'), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name='CustomUser', 20 | fields=[ 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('password', models.CharField(max_length=128, verbose_name='password')), 23 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), 24 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), 25 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), 26 | ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), 27 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), 28 | ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), 29 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), 30 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), 31 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), 32 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), 33 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), 34 | ], 35 | options={ 36 | 'db_table': 'custom_user', 37 | }, 38 | managers=[ 39 | ('objects', django.contrib.auth.models.UserManager()), 40 | ], 41 | ), 42 | ] 43 | -------------------------------------------------------------------------------- /accounts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akiyoko/django-auth-sample/d976650d484ed6b2dc743ba25b973f9ad5429523/accounts/migrations/__init__.py -------------------------------------------------------------------------------- /accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import AbstractUser 2 | 3 | 4 | class CustomUser(AbstractUser): 5 | """拡張ユーザーモデル""" 6 | 7 | class Meta: 8 | db_table = 'custom_user' 9 | -------------------------------------------------------------------------------- /accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /accounts/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'accounts' 6 | urlpatterns = [ 7 | path('signup/', views.SignupView.as_view(), name='signup'), 8 | ] 9 | -------------------------------------------------------------------------------- /accounts/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import login 2 | from django.urls import reverse_lazy 3 | from django.views.generic import CreateView 4 | 5 | from .forms import SignupForm 6 | 7 | 8 | class SignupView(CreateView): 9 | form_class = SignupForm 10 | success_url = reverse_lazy('home') 11 | template_name = 'registration/signup.html' 12 | 13 | def form_valid(self, form): 14 | # self.object に save() されたユーザーオブジェクトが格納される 15 | valid = super().form_valid(form) 16 | login(self.request, self.object) 17 | return valid 18 | -------------------------------------------------------------------------------- /config/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akiyoko/django-auth-sample/d976650d484ed6b2dc743ba25b973f9ad5429523/config/__init__.py -------------------------------------------------------------------------------- /config/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | ############### 5 | # Build paths # 6 | ############### 7 | 8 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 9 | PROJECT_NAME = os.path.basename(BASE_DIR) 10 | 11 | 12 | ##################### 13 | # Security settings # 14 | ##################### 15 | 16 | SECRET_KEY = '' 17 | 18 | DEBUG = True 19 | 20 | ALLOWED_HOSTS = ['*'] 21 | 22 | 23 | ################# 24 | # Core settings # 25 | ################# 26 | 27 | INSTALLED_APPS = [ 28 | 'django.contrib.admin', 29 | 'django.contrib.auth', 30 | 'django.contrib.contenttypes', 31 | 'django.contrib.sessions', 32 | 'django.contrib.messages', 33 | 'django.contrib.staticfiles', 34 | 'accounts.apps.AccountsConfig', 35 | ] 36 | 37 | MIDDLEWARE = [ 38 | 'django.middleware.security.SecurityMiddleware', 39 | 'django.contrib.sessions.middleware.SessionMiddleware', 40 | 'django.middleware.common.CommonMiddleware', 41 | 'django.middleware.csrf.CsrfViewMiddleware', 42 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 43 | 'django.contrib.messages.middleware.MessageMiddleware', 44 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 45 | ] 46 | 47 | ROOT_URLCONF = 'config.urls' 48 | 49 | TEMPLATES = [ 50 | { 51 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 52 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 53 | 'APP_DIRS': True, 54 | 'OPTIONS': { 55 | 'context_processors': [ 56 | 'django.template.context_processors.debug', 57 | 'django.template.context_processors.request', 58 | 'django.contrib.auth.context_processors.auth', 59 | 'django.contrib.messages.context_processors.messages', 60 | ], 61 | }, 62 | }, 63 | ] 64 | 65 | WSGI_APPLICATION = 'config.wsgi.application' 66 | 67 | 68 | ############ 69 | # Database # 70 | ############ 71 | 72 | DATABASES = { 73 | 'default': { 74 | 'ENGINE': 'django.db.backends.sqlite3', 75 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 76 | } 77 | } 78 | 79 | 80 | ####################### 81 | # Password validation # 82 | ####################### 83 | 84 | AUTH_PASSWORD_VALIDATORS = [ 85 | { 86 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 87 | }, 88 | { 89 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 90 | }, 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 93 | }, 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 96 | }, 97 | ] 98 | 99 | 100 | ######################## 101 | # Internationalization # 102 | ######################## 103 | 104 | LANGUAGE_CODE = 'ja' 105 | 106 | TIME_ZONE = 'Asia/Tokyo' 107 | 108 | USE_I18N = True 109 | 110 | USE_L10N = True 111 | 112 | USE_TZ = True 113 | 114 | 115 | ############ 116 | # Messages # 117 | ############ 118 | 119 | MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' 120 | 121 | 122 | ########### 123 | # Logging # 124 | ########### 125 | 126 | LOGGING = { 127 | 'version': 1, 128 | 'disable_existing_loggers': False, 129 | 'formatters': { 130 | 'develop': { 131 | 'format': '%(asctime)s [%(levelname)s] %(pathname)s:%(lineno)d ' 132 | '%(message)s' 133 | }, 134 | }, 135 | 'handlers': { 136 | 'console': { 137 | 'level': 'DEBUG', 138 | 'class': 'logging.StreamHandler', 139 | 'formatter': 'develop', 140 | }, 141 | }, 142 | 'loggers': { 143 | '': { 144 | 'handlers': ['console'], 145 | 'level': 'DEBUG', 146 | 'propagate': False, 147 | }, 148 | 'django': { 149 | 'handlers': ['console'], 150 | 'level': 'INFO', 151 | 'propagate': False, 152 | }, 153 | # 'django.db.backends': { 154 | # 'handlers': ['console'], 155 | # 'level': 'DEBUG', 156 | # 'propagate': False, 157 | # }, 158 | }, 159 | } 160 | 161 | 162 | ################ 163 | # Static files # 164 | ################ 165 | 166 | STATIC_URL = '/static/' 167 | STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] 168 | STATIC_ROOT = os.path.join(BASE_DIR, 'static_root') 169 | 170 | 171 | ################## 172 | # Authentication # 173 | ################## 174 | 175 | AUTH_USER_MODEL = 'accounts.CustomUser' 176 | 177 | LOGIN_REDIRECT_URL = 'home' 178 | LOGOUT_REDIRECT_URL = '/accounts/login/' 179 | 180 | 181 | ################## 182 | # Email settings # 183 | ################## 184 | 185 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' 186 | -------------------------------------------------------------------------------- /config/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | from django.views.generic import TemplateView 4 | 5 | urlpatterns = [ 6 | path('admin/', admin.site.urls), 7 | path('', TemplateView.as_view(template_name='home.html'), name='home'), 8 | path('accounts/', include('accounts.urls')), 9 | path('accounts/', include('django.contrib.auth.urls')), 10 | ] 11 | -------------------------------------------------------------------------------- /config/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for config 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', 'config.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /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', 'config.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 2 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% block title %}{% endblock %} 8 | 9 | {# --- css --- #} 10 | 12 | 17 | {% block extra_css %}{% endblock %} 18 | 19 | 20 |
21 | {% block content %}{% endblock %} 22 |
23 | 24 | {# --- js --- #} 25 | 28 | 31 | 34 | {% block extra_js %}{% endblock %} 35 | 36 | 37 | -------------------------------------------------------------------------------- /templates/home.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}ホーム{% endblock %} 4 | 5 | {% block content %} 6 |

ホーム

7 | {% if user.is_authenticated %} 8 | ようこそ {{ user.get_username }} さん 9 |

ログアウト

10 | {% else %} 11 |

ログイン

12 | {% endif %} 13 | {% endblock %} -------------------------------------------------------------------------------- /templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}ログイン{% endblock %} 4 | 5 | {% block content %} 6 |

ログイン

7 |
8 | {% csrf_token %} 9 | {{ form.as_p }} 10 | 11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /templates/registration/password_change_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}パスワード変更完了{% endblock %} 4 | 5 | {% block content %} 6 |

パスワード変更完了

7 | ホームに戻る 8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /templates/registration/password_change_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}パスワード変更{% endblock %} 4 | 5 | {% block content %} 6 |

パスワード変更

7 |
8 | {% csrf_token %} 9 | {{ form.as_p }} 10 | 11 |
12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /templates/registration/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}パスワード再設定完了{% endblock %} 4 | 5 | {% block content %} 6 |

パスワード再設定完了

7 |

ログインページに戻る

8 | {% endblock %} -------------------------------------------------------------------------------- /templates/registration/password_reset_confirm.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}パスワード再設定{% endblock %} 4 | 5 | {% block content %} 6 |

パスワード再設定

7 |
8 | {% csrf_token %} 9 | {{ form.as_p }} 10 | 11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /templates/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}パスワード再設定メール送信完了{% endblock %} 4 | 5 | {% block content %} 6 |

パスワード再設定メール送信完了

7 | ホームに戻る 8 | {% endblock %} -------------------------------------------------------------------------------- /templates/registration/password_reset_email.html: -------------------------------------------------------------------------------- 1 | {% autoescape off %} 2 | {{ user.get_username }} さん 3 | 4 | いつもご利用ありがとうございます。 5 | パスワード再設定の手続きを受け付けました。 6 | 以下のURLにアクセスして、新しいパスワードを設定してください。 7 | 8 | {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uid token %} 9 | 10 | ※このパスワード再設定URLの有効期限は3日間です。有効期限を過ぎると無効になります。 11 | {% endautoescape %} -------------------------------------------------------------------------------- /templates/registration/password_reset_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}パスワード再設定メール送信{% endblock %} 4 | 5 | {% block content %} 6 |

パスワード再設定メール送信

7 |
8 | {% csrf_token %} 9 | {{ form.as_p }} 10 | 11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /templates/registration/password_reset_subject.txt: -------------------------------------------------------------------------------- 1 | {% autoescape off %} 2 | パスワード再設定を受け付けました 3 | {% endautoescape %} -------------------------------------------------------------------------------- /templates/registration/signup.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}ユーザー登録{% endblock %} 4 | 5 | {% block content %} 6 |

ユーザー登録

7 |
8 | {% csrf_token %} 9 | {{ form.as_p }} 10 | 11 |
12 | {% endblock %} --------------------------------------------------------------------------------