質問編集履歴

2 内容の変更

omyu

omyu score 12

2019/10/10 11:55  投稿

djangoでログイン機能を作りたいのですが、loginfunc関数のauthenticateでの照合が、自分で作ったAddressModelではなく、djangoに元から備わっているUserオブジェクトにされている気がするのですが、もしそうなのであればどうすればAddressModelのオブジェクトと照合できるのか教えていただきたいです。
よろしくお願いします。
```python
djangoでUserというカスタムユーザーモデルを作り、djangoの管理画面にもそのカスタムユーザーモデルが適用されているのですが、views.pyのregister関数が呼び出すフォームで送信してもデータベースに保存されません。
どうすれば保存できるようになるか、また、UserCreationFormを継承するとパスワード入力欄が3つ出てきてしまうのですが、2つか1つにする方法も教えていただけると嬉しいです。
```python
###views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import CreateView, DeleteView
from django.urls import reverse_lazy
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from django.contrib.auth import authenticate, login, logout, get_user_model
from django.contrib.auth.decorators import login_required
from .forms import AddressModelCreateForm
from .models import AddressModel
User = get_user_model()
from .forms import UserCreateForm
from .models import User
# Create your views here.
def register(request):
   form = AddressModelCreateForm(request.POST or None)  
   if request.method == 'POST':
       try:
           form.save()
       form = UserCreateForm(request.POST)
       if form.is_valid():
           email = form.cleaned_data.get('email')
           password = form.cleaned_data.get('password')
           location = form.cleaned_data.get('location')
           user = User.objects.create_user(email, password, location)
           user.save()
           return redirect('register_comp')
       except ValueError:
           return render(request, 'register.html', {
               'error': 'このメールアドレスは登録されています',
               'form': AddressModelCreateForm()
           })
       
           
   return render(request, 'register.html', {'form': AddressModelCreateForm()})
def registercomp(request):
   return render(request, 'register_comp.html', {'message': '登録が完了しました'})
@login_required
def update(request, pk):
   addressModel = get_object_or_404(AddressModel, pk=pk)
   form = AddressModelCreateForm(request.POST or None, instance=addressModel)
   if request.method == 'POST' and form.is_valid():
       form.save()
       return redirect('register_comp')
   return render(request, 'update.html', {'form': form})
def loginfunc(request):
   if request.method == 'POST':
       username = request.POST['username']
       password = request.POST['password']
       user = authenticate(request, username=username, password=password)
   
       if user is not None:
           login(request, user)
           return redirect('login')
       else:
           return render(request, 'login.html', {
               'error': '未登録ユーザーです',
               'form': AddressModelCreateForm()
           })
           
   return render(request, 'login.html', {'form': AddressModelCreateForm()})
   return render(request, 'register.html', {'form': UserCreateForm()})
```
```html
###login.html
{% extends 'base.html' %}
{% block header %}
<div class="jumbotron jumbotron-fluid">
   <div class="container">
       <h1 class="display-4">Weather Mail</h1>
       <p class="lead">毎朝7時にメールをお届けします。</p>
   </div>
</div>
{% endblock header %}
{% block content %}
<h2>ログイン</h2>
{% if error %}
<p>{{ error }}</p>
{% endif %}
<form action="" method="POST">{% csrf_token %}
   <p>ユーザーネーム: {{ form.username }}</p>
   <p>パスワード: {{ form.password }}</p>
   <button type="submit" class="btn btn-primary">ログイン</button>
   <a href="{% url 'register' %}" class="btn btn-primary">新規登録</a>
</form>
{% endblock content %}
```python
###models.py
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
 
 
class UserManager(BaseUserManager):
   """ユーザーマネージャー."""
 
   use_in_migrations = True
 
   def _create_user(self, email, password, **extra_fields):
       """Create and save a user with the given username, email, and
       password."""
       if not email:
           raise ValueError('The given email must be set')
       email = self.normalize_email(email)
 
       user = self.model(email=email, **extra_fields)
       user.set_password(password)
       user.save(using=self._db)
       return user
 
   def create_user(self, email, password=None, **extra_fields):
       extra_fields.setdefault('is_staff', False)
       extra_fields.setdefault('is_superuser', False)
       return self._create_user(email, password, **extra_fields)
 
   def create_superuser(self, 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(email, password, **extra_fields)
 
 
LOCATION = (('130010', '東京'), ('230010', '名古屋'), ('270000', '大阪'), ('400010', '福岡'))
class User(AbstractBaseUser, PermissionsMixin):
   """カスタムユーザーモデル."""
 
   email = models.EmailField(_('email address'), unique=True)
   first_name = models.CharField(_('first name'), max_length=30, blank=True)
   last_name = models.CharField(_('last name'), max_length=150, blank=True)
   location = models.CharField(
       '住所',
       max_length = 20,
       choices = LOCATION
   )
 
   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 = 'email'
   REQUIRED_FIELDS = []
 
   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)
```
```python
###forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import get_user_model
User = get_user_model()
class UserCreateForm(UserCreationForm):
   password = forms.CharField(widget=forms.PasswordInput)
   password1 = forms.CharField(required=False)
   password2 = password1
   class Meta:
       model = User
       fields = ('email', 'password', 'location')
```
```python
"""
Django settings for weathermailproject project.
Generated by 'django-admin startproject' using Django 2.2.5.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '_3&*rp@a@yxu1_8%w%rw7qh7&^@57#15s6(mbep2(1&!nl8=+h'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
   'django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',
   'weathermail',
]
MIDDLEWARE = [
   'django.middleware.security.SecurityMiddleware',
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.common.CommonMiddleware',
   'django.middleware.csrf.CsrfViewMiddleware',
   'django.contrib.auth.middleware.AuthenticationMiddleware',
   'django.contrib.messages.middleware.MessageMiddleware',
   'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'weathermailproject.urls'
TEMPLATES = [
   {
       'BACKEND': 'django.template.backends.django.DjangoTemplates',
       'DIRS': [BASE_DIR, 'templates'],
       'APP_DIRS': True,
       'OPTIONS': {
           'context_processors': [
               'django.template.context_processors.debug',
               'django.template.context_processors.request',
               'django.contrib.auth.context_processors.auth',
               'django.contrib.messages.context_processors.messages',
           ],
       },
   },
]
WSGI_APPLICATION = 'weathermailproject.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.sqlite3',
       'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
   }
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
   {
       'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
   },
   {
       'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
   },
   {
       'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
   },
   {
       'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
   },
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
LOGIN_URL = 'login'
AUTH_USER_MODEL = 'weathermail.User'
```
  • Python

    17362 questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Django

    2364 questions

    DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

  • Python 3.x

    13435 questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1 内容の変更

omyu

omyu score 12

2019/10/08 23:20  投稿

djangoでログイン機能を作りたい
djangoでログイン機能を作ろうとしてloginfuncという関数を書いたのですが、確かにあるはずのユーザーネームとパスワードでログインしようとしても、『未登録ユーザーです』というエラー文を表示するelseの方に引っかかってしまいます。
原因がわかる方がいらっしゃいましたら教えていただきたいです。
djangoでログイン機能を作りたいのですが、loginfunc関数のauthenticateでの照合が、自分で作ったAddressModelではなく、djangoに元から備わっているUserオブジェクトにされている気がするのですが、もしそうなのであればどうすればAddressModelのオブジェクトと照合できるのか教えていただきたいです。
よろしくお願いします。
```python
from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import CreateView, DeleteView
from django.urls import reverse_lazy
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from .forms import AddressModelCreateForm
from .models import AddressModel
# Create your views here.
def register(request):
   form = AddressModelCreateForm(request.POST or None)
   if request.method == 'POST':
       try:
           form.save()
           return redirect('register_comp')
       except ValueError:
           return render(request, 'register.html', {
               'error': 'このメールアドレスは登録されています',
               'form': AddressModelCreateForm()
           })
           
   return render(request, 'register.html', {'form': AddressModelCreateForm()})
def registercomp(request):
   return render(request, 'register_comp.html', {'message': '登録が完了しました'})
@login_required
def update(request, pk):
   addressModel = get_object_or_404(AddressModel, pk=pk)
   form = AddressModelCreateForm(request.POST or None, instance=addressModel)
   if request.method == 'POST' and form.is_valid():
       form.save()
       return redirect('register_comp')
   return render(request, 'update.html', {'form': form})
def loginfunc(request):
   if request.method == 'POST':
       username = request.POST['username']
       password = request.POST['password']
       user = authenticate(request, username=username, password=password)
   
       if user is not None:
           login(request, user)
           return redirect('login')
       else:
           return render(request, 'login.html', {
               'error': '未登録ユーザーです',
               'form': AddressModelCreateForm()
           })
           
   return render(request, 'login.html', {'form': AddressModelCreateForm()})
```
```html
###login.html
{% extends 'base.html' %}
{% block header %}
<div class="jumbotron jumbotron-fluid">
   <div class="container">
       <h1 class="display-4">Weather Mail</h1>
       <p class="lead">毎朝7時にメールをお届けします。</p>
   </div>
</div>
{% endblock header %}
{% block content %}
<h2>ログイン</h2>
{% if error %}
<p>{{ error }}</p>
{% endif %}
<form action="" method="POST">{% csrf_token %}
   <p>ユーザーネーム: {{ form.username }}</p>
   <p>パスワード: {{ form.password }}</p>
   <button type="submit" class="btn btn-primary">ログイン</button>
   <a href="{% url 'register' %}" class="btn btn-primary">新規登録</a>
</form>
{% endblock content %}
```
  • Python

    17362 questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Django

    2364 questions

    DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

  • Python 3.x

    13435 questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る