

### 前提・実現したいこと

独自のモデルを用いて，authenticateを使うために，認証バックエンドをカスタマイズしていました

### 発生している問題・エラーメッセージ

エラーがUserdataにcheck_passwordが定義されていないからこういった問題が起こったという風に記載されていることはわかります。ただ，参考サイトの方でもUserにcheck_passwordが設定されていないのに，自分のmodelの場合こういったエラーが生じるのかわかりません。また，具体的にどのように，check_passwordをどのように導入すべきなのかもわからないのでその点もご教授お願い致します。

[code]

    File "C:\Users\ユーザー名\testapp\content\backends.py", line 11, in authenticate
        if user.check_password(password) and self.user_can_authenticate(user):
    AttributeError: 'Userdata' object has no attribute 'check_password'
    
[/code]

### 該当のソースコード

backends.py

[code]

    from django.contrib.auth.backends import ModelBackend
    from .models import Userdata
    
    class Userbackend(ModelBackend):
      def authenticate(self,request,email=None,password=None,**kwargs):
        try:
          user=Userdata.objects.get(email=email)
        except Userdata.DoesNotExist:
          return None
        else:
          if user.check_password(password) and self.user_can_authenticate(user):
            return user
    
[/code]

models.py

[code]

    #ユーザー登録
    class Userdata(models.Model):
      name = models.CharField(verbose_name='ユーザー名',max_length=15,unique=True)
      email = models.EmailField(verbose_name='ユーザーid',max_length=30,unique=True)
      password = models.CharField(verbose_name='パスワード',max_length=15)
      regist_date = models.DateTimeField(default=timezone.now)
    
[/code]

### 試したこと

次のサイトを参考にし認証バックエンドをカスタマイズしていました。  
(<https://django.kurodigi.com/customize-auth-backend/>)

参考サイトのmodels.pyが別のページにありましたので下記のサイトを参考に指定ください  
(<https://django.kurodigi.com/custamize-user/>)

### 補足情報（FW/ツールのバージョンなど）

ディレクトリ構成  
testapp/  
├ content/  
│ ├ backends.py  
│ ├models.py  
  
Python 3.9.5  
django 3.2.5

参考サイトのbackends.pyとmodels.pyの該当箇所と思われる箇所のコードは次のようになっていました。  
backend.py

[code]

    from django.contrib.auth.backends import ModelBackend
    from .models import User
    
    class EmailAuthBackend(ModelBackend):
        def authenticate(self, request, email=None, password=None, **kwargs):
            try:
                user = User.objects.get(email=email)
            except User.DoseNotExist:
                return None
            else:
                if user.check_password(password) and self.user_can_authenticate(user):
                    return user
    
[/code]

models.py

[code]

    class User(AbstractBaseUser, PermissionsMixin):
        """
        Django標準のUserをベースにカスタマイズしたUserクラス
        """
        username_validator = UnicodeUsernameValidator()
        # python3で半角英数のみ許容する場合はASCIIUsernameValidatorを用いる
        # username_validator = ASCIIUsernameValidator()
    
        username = models.CharField(
            _('username'),
            max_length=50,
            unique=True,
            # help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
            help_text='この項目は必須です。全角文字、半角英数字、@/./+/-/_ で50文字以下にしてください。',
            validators=[username_validator],
            error_messages={
                'unique': _("A user with that username already exists."),
            },
        )
        # first_name = models.CharField(_('first name'), max_length=30, blank=True)
        # last_name = models.CharField(_('last name'), max_length=150, blank=True)
        email = models.EmailField(
            _('email address'),
            help_text='この項目は必須です。メールアドレスは公開されません。',
            blank=False
        )
        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')
            # abstract = True
            abstract = False
    
        def clean(self):
            super().clean()
            self.email = self.__class__.objects.normalize_email(self.email)
    
        # first_nameとlast_nameに関する部分はコメントアウト
        # 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)
    
[/code]


CC BY-SA 4.0
2021-08-03T05:53:59.180
80559
2021-08-07T22:05:07.690
2021-08-03T07:31:58.037
45546
45546
question
python django
AttributeError: 'Userdata' object has no attribute 'check_password'


modelsの最終的な形として次のような書き方をしたところ解決しました。

[code]

    #ユーザー登録
    class UserManager(BaseUserManager):
    
      use_in_migrations=True#migration時に特殊な操作をするとき必要なのでなくても構わない
    
    　#一般ユーザーの動作
      def create_user(self,username,email,date,password=None):
        if not username:
          raise ValueError('The given username must be set')
        elif not email:
          raise ValueError('The given email must be set')
        user = self.model(
          name=username,
          email = self.normalize_email(email),
          regist_date=date,
        )
        user.set_password(password)
        user.save(using=self._db)
        return user
    
      #superuserの動作
      def create_superuser(self,username,email,password):
        user=self.create_user(
          username,
          email,
          password=password
        )
        user.is_admin =True
        user.save(using=self._db)
        return user
    
    class Userdata(AbstractBaseUser,PermissionsMixin):
    　#使いたい独自のmodel
      name = models.CharField(verbose_name='ユーザー名',max_length=50,unique=True)
      email = models.EmailField(verbose_name='ユーザーid',max_length=30,unique=True)
      password = models.CharField(verbose_name='パスワード',max_length=15)
      date_joined = models.DateTimeField(default=timezone.now)
      is_staff = models.BooleanField(default=False)
      is_active = models.BooleanField(default=True)
    
      #Userdata.objects.all()とかで使うobjects
      objects=UserManager()
    
      EMAIL_FIELD = 'email'(ユーザーがパスワード変更時にemailでのチェック可能とするために必要)
      USERNAME_FIELD = 'email'(認証に使いたいものを記載 
    　　　　　　　　　　　　　　　　username認証の場合:USERNAME_FIELD = 'username'
                                 email認証の場合: USERNAME_FIELD = 'email'
    　　　　　　　　　　　　　　　)
      REQUIRED_FIELDS = []#createsuperuserの時に聞かれる追加項目
    
[/code]


CC BY-SA 4.0
2021-08-07T22:05:07.690
80663
2021-08-07T22:05:07.690
45546
80559
answer