python Django自定义用户模型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python Django自定义用户模型相关的知识,希望对你有一定的参考价值。
from django.conf import settings
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import ugettext_lazy as _
# registerのUserモデルを使う場合だけ、登録する
if settings.AUTH_USER_MODEL == 'register.User':
from .models import User
class MyUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = '__all__'
class MyUserCreationForm(UserCreationForm):
class Meta:
model = User
# fields = ('email',)
fields = ('username', 'email')
class MyUserAdmin(UserAdmin):
form = MyUserChangeForm
add_form = MyUserCreationForm
list_display = ('username', 'email', 'last_name', 'first_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
# search_fields = ('email', 'first_name', 'last_name')
# ordering = ('email',)
admin.site.register(User, MyUserAdmin)
# カスタムユーザーを使う
AUTH_USER_MODEL = 'register.User'
from django import forms
from django.contrib.auth.forms import (
AuthenticationForm, UserCreationForm, PasswordChangeForm,
PasswordResetForm, SetPasswordForm
)
from django.contrib.auth import get_user_model
from .models import UserProfile
import bootstrap_datepicker_plus as datetimepicker
User = get_user_model()
class LoginForm(AuthenticationForm):
"""ログインフォーム"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
field.widget.attrs['placeholder'] = field.label # placeholderにフィールドのラベルを入れる
class UserCreateForm(UserCreationForm):
"""ユーザー登録用フォーム"""
class Meta:
model = User
if User.USERNAME_FIELD == 'email':
fields = ('email',)
else:
fields = ('username', 'email')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
class UserUpdateForm(forms.ModelForm):
"""ユーザー情報更新フォーム"""
class Meta:
model = User
if User.USERNAME_FIELD == 'email':
fields = ('email', 'last_name', 'first_name')
else:
fields = ('username', 'email', 'last_name', 'first_name')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
class MyPasswordChangeForm(PasswordChangeForm):
"""パスワード変更フォーム"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
class MyPasswordResetForm(PasswordResetForm):
"""パスワード忘れたときのフォーム"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
class MySetPasswordForm(SetPasswordForm):
"""パスワード再設定用フォーム(パスワード忘れて再設定)"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
class InputProfileForm1(forms.Form):
birth = forms.DecimalField(
label = '生年月日(西暦)',
required=True,
widget = datetimepicker.DatePickerInput( # スマホ対応版 キーボード入力不可
format = '%Y-%m-%d',
attrs={'readonly': 'true'},
options = {
'locale':'ja',
'dayViewHeaderFormat': 'YYYY年 MMMM',
'ignoreReadonly': True,
'allowInputToggle': True,
}
),
)
height = forms.DecimalField(
max_digits=4,
decimal_places=1,
max_value=220,
min_value=100,
label = '身長(cm)',
required=True,
)
class InputProfileForm(forms.ModelForm):
"""ユーザープロファイル更新フォーム"""
class Meta:
model = UserProfile
fields = ('birth', 'height')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
from django.conf import settings
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import ugettext_lazy as _
# registerのUserモデルを使う場合だけ、登録する
if settings.AUTH_USER_MODEL == 'register.User':
from .models import User
class MyUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = '__all__'
class MyUserCreationForm(UserCreationForm):
class Meta:
model = User
# fields = ('email',)
fields = ('username', 'email')
class MyUserAdmin(UserAdmin):
form = MyUserChangeForm
add_form = MyUserCreationForm
list_display = ('username', 'email', 'last_name', 'first_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
# search_fields = ('email', 'first_name', 'last_name')
# ordering = ('email',)
admin.site.register(User, MyUserAdmin)
from django.conf import settings
from django.db import models
from django.core.mail import send_mail
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _ # 翻訳置換
from django.utils import timezone
from django.contrib.auth.base_user import BaseUserManager
# registerのUserモデルを使う場合だけ、登録する
if settings.AUTH_USER_MODEL == 'register.User':
class UserManager(BaseUserManager):
"""ユーザーマネージャー"""
use_in_migrations = True
def _create_user(self, username, email, password, **extra_fields):
"""Create and save a user with the given username, email, and
password."""
if not username:
raise ValueError('The given username must be set')
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(username=username, email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(username, email, password, **extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(username, email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
"""カスタムユーザーモデル
usernameを使わず、emailアドレスをユーザー名として使うようにしています。
⇒ username再追加(デフォルトUserクラスと同じ)
"""
username = models.CharField(_('username'), max_length=30, unique=True)
email = models.EmailField(_('email address'), unique=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_(
'Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
"""Return the first_name plus the last_name, with a space in
between."""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""Return the short name for the user."""
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
#@property
#def username(self):
# return self.email
# ユーザーの追加情報 1:1レコード
class UserProfile(models.Model):
owner = models.OneToOneField(User, on_delete=models.CASCADE, related_name='prifile_owner')
birth = models.DateField(
_('birth'),
# verbose_name = '誕生日',
help_text ='生年月日。例 1970-04-01',
) # 生年月日
height = models.DecimalField(
_('height'),
max_digits=4,
decimal_places=1,
# verbose_name = '身長',
help_text ='身長をcm単位で。例 155.3',
) # 身長(cm)
from django.urls import path
from . import views
from django.views.generic import RedirectView
app_name = 'register'
urlpatterns = [
path('', views.Top.as_view(), name='top'),
#path('', RedirectView.as_view(url='/register/login')),
path('login/', views.Login.as_view(), name='login'),
# path('logout/', RedirectView.as_view(url='/register/login'), name='logout'),
path('logout/', views.Logout.as_view(), name='logout'),
path('user_create/', views.UserCreate.as_view(), name='user_create'),
path('user_create/done/', views.UserCreateDone.as_view(), name='user_create_done'),
path('user_create/complete/<token>/', views.UserCreateComplete.as_view(), name='user_create_complete'), #本登録用URL(<token>)
path('user_detail/<int:pk>/', views.UserDetail.as_view(), name='user_detail'),
path('user_update/<int:pk>/', views.UserUpdate.as_view(), name='user_update'),
path('password_change/', views.PasswordChange.as_view(), name='password_change'),
path('password_change/done/', views.PasswordChangeDone.as_view(), name='password_change_done'),
path('password_reset/', views.PasswordReset.as_view(), name='password_reset'),
path('password_reset/done/', views.PasswordResetDone.as_view(), name='password_reset_done'),
path('password_reset/confirm/<uidb64>/<token>/', views.PasswordResetConfirm.as_view(), name='password_reset_confirm'),
path('password_reset/complete/', views.PasswordResetComplete.as_view(), name='password_reset_complete'),
]
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.views import (
LoginView, LogoutView, PasswordChangeView, PasswordChangeDoneView,
PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView, PasswordResetCompleteView
)
from django.contrib.sites.shortcuts import get_current_site
from django.core.signing import BadSignature, SignatureExpired, loads, dumps
from django.http import HttpResponseBadRequest
from django.shortcuts import redirect, resolve_url
from django.template.loader import get_template
from django.urls import reverse_lazy
from django.utils import timezone
from django.views import generic
from .forms import (
LoginForm, UserCreateForm, UserUpdateForm, MyPasswordChangeForm,
MyPasswordResetForm, MySetPasswordForm,
InputProfileForm,
)
from ap01diet.models import UserProfile
User = get_user_model()
class Top(generic.TemplateView):
template_name = 'register/top.html'
class Login(LoginView):
"""ログインページ"""
form_class = LoginForm
template_name = 'register/login.html'
class Logout(LoginRequiredMixin, LogoutView):
"""ログアウトページ"""
template_name = 'register/top.html'
class UserCreate(generic.CreateView):
"""ユーザー仮登録"""
template_name = 'register/user_create.html'
form_class = UserCreateForm
def form_valid(self, form):
"""仮登録と本登録用メールの発行."""
# 仮登録と本登録の切り替えは、is_active属性を使うと簡単です。
# 退会処理も、is_activeをFalseにするだけにしておくと捗ります。
user = form.save(commit=False)
user.is_active = False
user.save()
# アクティベーションURLの送付
current_site = get_current_site(self.request)
domain = current_site.domain
context = {
'protocol': 'https' if self.request.is_secure() else 'http',
'domain': domain,
'token': dumps(user.pk),
'user': user,
}
subject_template = get_template('register/mail_template/create/subject.txt')
subject = subject_template.render(context)
message_template = get_template('register/mail_template/create/message.txt')
message = message_template.render(context)
user.email_user(subject, message)
return redirect('register:user_create_done')
class UserCreateDone(generic.TemplateView):
"""ユーザー仮登録したよ"""
template_name = 'register/user_create_done.html'
class UserCreateComplete(generic.TemplateView):
"""メール内URLアクセス後のユーザー本登録"""
template_name = 'register/user_create_complete.html'
timeout_seconds = getattr(settings, 'ACTIVATION_TIMEOUT_SECONDS', 60*60*24) # デフォルトでは1日以内
def get(self, request, **kwargs):
"""tokenが正しければ本登録."""
token = kwargs.get('token')
try:
user_pk = loads(token, max_age=self.timeout_seconds)
# 期限切れ
except SignatureExpired:
return HttpResponseBadRequest()
# tokenが間違っている
except BadSignature:
return HttpResponseBadRequest()
# tokenは問題なし
else:
try:
user = User.objects.get(pk=user_pk)
except User.DoenNotExist:
return HttpResponseBadRequest()
else:
if not user.is_active:
# まだ仮登録で、他に問題なければ本登録とする
user.is_active = True
user.save()
return super().get(request, **kwargs)
return HttpResponseBadRequest()
class OnlyYouMixin(UserPassesTestMixin):
"""本人か、スーパーユーザーだけユーザーページアクセスを許可する"""
raise_exception = True
def test_func(self):
user = self.request.user
return user.pk == self.kwargs['pk'] or user.is_superuser
class UserDetail(OnlyYouMixin, generic.DetailView):
"""ユーザーの詳細ページ"""
model = User
template_name = 'register/user_detail.html' # デフォルトユーザーを使う場合に備え、きちんとtemplate名を書く
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
pk = self.kwargs['pk']
me = User.objects.get(id=pk)
if UserProfile.objects.filter(owner=me).exists():
context['prof'] = UserProfile.objects.filter(owner=me)[0]
else:
context['prof'] = None
return context
class UserUpdate(OnlyYouMixin, generic.UpdateView):
"""ユーザー情報更新ページ"""
model = User
form_class = UserUpdateForm
template_name = 'register/user_form.html' # デフォルトユーザーを使う場合に備え、きちんとtemplate名を書く
def get_success_url(self):
return resolve_url('register:user_detail', pk=self.kwargs['pk'])
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
pk = self.kwargs['pk']
# me = User.objects.filter(id=pk)
if UserProfile.objects.filter(id=pk).exists():
myprof = UserProfile.objects.filter(id=pk)[0]
initial={
# 'date':myobj0.date,
'birth':myprof.birth,
'height':myprof.height,
}
else:
initial={
'birth': "1970-01-01",
'height':150.0,
}
context['form_parof'] = InputProfileForm(
initial = initial
)
return context
def post(self, request, *args, **kwargs):
# User DBの更新
super().post(request, *args, **kwargs)
# Profile DBの更新
pk = self.kwargs['pk']
d = UserProfile.objects.filter(id=pk)[0]
d.updated_by = self.request.user
d.updated_at = timezone.now()
d.height = request.POST['height']
d.birth = request.POST['birth']
d.save()
return redirect('register:user_detail', pk=self.kwargs['pk'])
class PasswordChange(PasswordChangeView):
"""パスワード変更ビュー"""
form_class = MyPasswordChangeForm
success_url = reverse_lazy('register:password_change_done')
template_name = 'register/password_change.html'
class PasswordChangeDone(PasswordChangeDoneView):
"""パスワード変更しました"""
template_name = 'register/password_change_done.html'
class PasswordReset(PasswordResetView):
"""パスワード変更用URLの送付ページ"""
subject_template_name = 'register/mail_template/password_reset/subject.txt'
email_template_name = 'register/mail_template/password_reset/message.txt'
template_name = 'register/password_reset_form.html'
form_class = MyPasswordResetForm
success_url = reverse_lazy('register:password_reset_done')
class PasswordResetDone(PasswordResetDoneView):
"""パスワード変更用URLを送りましたページ"""
template_name = 'register/password_reset_done.html'
class PasswordResetConfirm(PasswordResetConfirmView):
"""新パスワード入力ページ"""
form_class = MySetPasswordForm
success_url = reverse_lazy('register:password_reset_complete')
template_name = 'register/password_reset_confirm.html'
class PasswordResetComplete(PasswordResetCompleteView):
"""新パスワード設定しましたページ"""
template_name = 'register/password_reset_complete.html'
以上是关于python Django自定义用户模型的主要内容,如果未能解决你的问题,请参考以下文章