djangoのUserモデルと4つの拡張/書き換え方法

11745 ワード

UserモデルUserモデルはこのフレームワークのコア部分である.彼の完全な経路はdjango.contrib.auth.models.Userです.このUserオブジェクトについて簡単に説明します.
フィールド:
内蔵のUserモデルには、次のフィールドがあります.
  • username:ユーザー名.150文字以内.数字および英字文字、ならびに_@+.-およびfirst_name文字を含むことができる.空にすることはできません.一意でなければなりません.
  • first_name:歪果仁のlast_name、30文字以内.空にできます.
  • last_name:歪果仁のemail、150文字以内.空にできます.
  • password:メールボックス.空にできます.
  • groups:パスワード.ハッシュ後のパスワード.
  • groups:グループ化.1つのユーザは複数のパケットに属することができ、1つのパケットは複数のユーザを持つことができる.Groupこのフィールドは、user_permissionsとの多対多の関係である.
  • Permission:権限.1つのユーザは複数の権限を持つことができ、1つの権限は複数のユーザによって所有されることができる.is_staffとは多対多の関係に属する.
  • admin:is_activeのサイトにアクセスできるかどうか.従業員かどうかを表します.
  • False:利用可能かどうか.アカウントを削除したいデータについては、実際にデータベースから削除するのではなく、is_superuserに設定すればいいです.
  • last_login:スーパー管理者かどうか.スーパーアドミニストレータの場合は、Webサイト全体のすべての権限があります.
  • date_joined:前回登録した時刻.
  • Django:アカウントが作成された時間.

  • ログインの検証:django.contrib.auth.authenticateの認証システムは、ログイン検証の機能を実現しました.usernameで実現できます.この方法はpasswordDjangoでしか検証できない.サンプルコードは次のとおりです.
    from django.contrib.auth import authenticate
    user = authenticate(username='Tom', password='111111')
    #        ,        user  。
    if user is not None:
        #           
    else:
        #            。

    拡張ユーザーモデル:Userに内蔵されたDjangoモデルは十分強いですが.しかし、時には私たちのニーズを満たすことができません.例えば、ユーザーのログインを検証する際には、ユーザー名を検証として使用していますが、携帯電話番号やメールボックスで検証する必要がある場合があります.たとえば、新しいフィールドを追加したい場合もあります.では、ユーザーモデルを拡張する必要があります.ユーザーモデルを拡張するには、さまざまな方法があります.ここでは一つ一つ検討してみましょう.
    1.Proxyモデルを設定するには:
    作用:モデルに操作方法を追加する
    制限:Userモデルのフィールドを増やしたり減らしたりすることはできません.
    メリット:元のUserモデルのテーブル構造を破壊しないPersonで提供されたフィールドと検証方法に満足している場合は、変更する必要はありません.しかし、彼の元の基礎の上でいくつかの操作方法を増やす必要があります.では、この方法をお勧めします.サンプルコードは次のとおりです.
    # models.py
    class Person(User):
        #            
        #                Field
        # telephone = models.CharField(max_length=11)  #     
        class Meta:
            proxy = True
    
        # proxy               
        #            
        def get_blacklist(self):
            return self.objects.filter(is_active=False)

    以上、Userクラスを定義し、Metaから継承させ、proxy=TrueUserを設定し、これはUserのエージェントモデルにすぎないことを示した.彼は、Person.get_blacklist()モデルのデータベース内のテーブルの構造に影響を与えません.後ですべてのブラックリストを簡単に取得したい人は、User.objects.all()で取得できます.そしてPerson.objects.all()Userは実際には等価である.authenticateというモデルからすべてのデータを取得しているからです.
    2.一対一の外部キー:
    役割:モデルに新しいフィールド、新しいメソッドを追加する
    制限:追加のみ、フィールドを減らすことはできません.ユーザー検証方法を変更することはできません.authenticateメリット:元のUserモデルのテーブル構造を破壊しない
    ユーザー認証方法usernameに他の要件がない場合は、passwordUserExtensionを使用して完了します.ただし、元のモデルのベースに新しいフィールドを追加するには、一対一の外部キーを使用します.サンプルコードは次のとおりです.
    # models.py
    from django.contrib.auth.models import User
    from django.db import models
    from django.dispatch import receiver
    from django.db.models.signals import post_save
    
    class UserExtension(models.Model):
        user = models.OneToOneField(User,on_delete=models.CASCADE,related_name='extension')
        birthday = models.DateField(null=True,blank=True)
        school = models.CharField(max_length=100)
    
    
    @receiver(post_save,sender=User)
    def create_user_extension(sender,instance,created,**kwargs):
        if created:
            UserExtension.objects.create(user=instance)
        else:
            instance.extension.save()

    以上、Userのモデルを定義し、UserExtensionのモデルと1対1のバインドを行い、その後、新しいフィールドをUserに追加しました.さらに、saveUserExtensionメソッドを呼び出すと、UserおよびAbstractUserがバインドされる保存モデルを受信する信号処理方法も記載されている.
    # views.py
    from django.contrib.auth.models import User
    from django.http import HttpResponse
    
    
    def one_to_one_view(request):
        user = User.objects.create_user(username='Tom',email='[email protected]',password='111111')
        #          
        user.extension.school = 'Harvard'
        user.save()
        return HttpResponse('     User  ')

    3.authenticateから継承:
    役割:モデルに新しいフィールドを追加し、ユーザー検証方法を変更します:authenticate制限:フィールドを減らすことはできません.
    デメリット:元のUserモデルのテーブル構造を破壊するUserに不満があり、元のdjango.contrib.auth.models.AbstractUserオブジェクトのフィールドの一部を変更したくないが、いくつかのフィールドを追加したい場合は、django.contrib.auth.models.Userから直接継承することができ、実際にはこのクラスもUserの親である.たとえば、telephoneモデルにschoolフィールドとsettingsフィールドを追加したいとします.サンプルコードは次のとおりです.
    # models.py
    from django.contrib.auth.models import AbstractUser
    class User(AbstractUser):
        telephone = models.CharField(max_length=11,unique=True)
        school = models.CharField(max_length=100)
        #   telephone  USERNAME_FIELD,       username  ,   username   
        username = models.CharField(max_length=150)
    
        #   telephone  USERNAME_FIELD,    authenticate
        #        ,     telephone   
        #       username
        USERNAME_FIELD = 'telephone'
        # USERNAME_FIELD   'telephone'               
        #  []           ,   ['username', 'email']
        REQUIRED_FIELDS = []
    
        #     Manager  ,   user     telephone 
        # password,     username password
        objects = UserManager()
    
    
    #   UserManager
    class UserManager(BaseUserManager):
        use_in_migrations = True
    
        def _create_user(self, telephone, password, **extra_fields):
            if not telephone:
                raise ValueError("       !")
            if not password:
                raise ValueError("     !")
            user = self.model(telephone=telephone, **extra_fields)
            user.set_password(password)
            user.save(using=self._db)
            return user
    
        def create_user(self, telephone, password, **extra_fields):
            extra_fields.setdefault('is_staff', False)
            extra_fields.setdefault('is_superuser', False)
            return self._create_user(telephone, password, **extra_fields)
    
        def create_superuser(self, telephone, 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(telephone, password, **extra_fields)

    そしてmigrateに配置します
    # settings.py
    AUTH_USER_MODEL = 'youappname.User'

    この方式は元のUserモデルのテーブル構造を破壊するので,1回目のAbstractBaseUserまでに定義しなければならない.
    4.authenticateモデルから継承:
    役割:モデルにフィールドを追加または減少し、ユーザー検証方法を変更します:AbstractBaseUser PermissionsMixinデメリット:元のUserモデルのテーブル構造を破壊する
    注:Userから継承
    デフォルトの検証方法を変更し、元のAbstractBaseUserモデルのフィールドの一部が望ましくない場合は、モデルをカスタマイズしてDjangoから継承し、希望するフィールドを追加できます.この方法は面倒なので、passwordについてよく知っていることを確認してからお勧めします.手順は次のとおりです.
  • モデルを作成します.サンプルコードは、
    # models.py
    from django.contrib.auth.base_user import AbstractBaseUser
    from django.contrib.auth.models import PermissionsMixin
    from django.db import models
    
    
    class User(AbstractBaseUser,PermissionsMixin):
         email = models.EmailField(unique=True)
         username = models.CharField(max_length=150)
         telephone = models.CharField(max_length=11,unique=True)
         is_staff = models.BooleanField(default=False)
         is_active = models.BooleanField(default=True)
    
         USERNAME_FIELD = 'telephone'
         REQUIRED_FIELDS = []
    
        #    UserManager   3,     
         objects = UserManager()
    
         def get_full_name(self):
             return self.username
    
         def get_short_name(self):
             return self.username
    です.last_loginAbstractBaseUseremailに追加されています.直接継承すればいいです.次に、希望するフィールドを追加します.例えばusernametelephoneUser等である.これで自分の望むフィールドを実現できます.しかし、Userを書き換えたので、できるだけUSERNAME_FIELDモデルをシミュレートする必要があります.
  • User:USERNAMEモデルの名前フィールドを記述するために使用される文字列.変更されていない場合は、REQUIRED_FIELDSが一意のフィールドとして使用されます.
  • createsuperuser:is_active管理コマンドによってユーザが作成されたときのプロンプトに使用されるフィールド名のリスト.
  • get_full_name():ユーザーが現在使用可能かどうかを識別するブール値.
  • get_short_name():完全な名前を取得します.
  • UserManager:比較的短いユーザー名.

  • UserManagerを再定義します.デフォルトのUserManagerは、ユーザーの作成時にusernamepasswordを使用しているので、telephoneに置き換えます.サンプルコードは次のとおりです:
    # models.py
    from django.contrib.auth.base_user import BaseUserManager
    
    
    #   UserManager
    class UserManager(BaseUserManager):
        use_in_migrations = True
    
        def _create_user(self, telephone, password, **extra_fields):
            if not telephone:
                raise ValueError("       !")
            if not password:
                raise ValueError("     !")
            user = self.model(telephone=telephone, **extra_fields)
            user.set_password(password)
            user.save(using=self._db)
            return user
    
        def create_user(self, telephone, password, **extra_fields):
            extra_fields.setdefault('is_staff', False)
            extra_fields.setdefault('is_superuser', False)
            return self._create_user(telephone, password, **extra_fields)
    
        def create_superuser(self, telephone, 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(telephone, password, **extra_fields)
  • は、新しいUserモデルを作成した後、settingsで構成する必要があります.構成AUTH_USER_MODEL='appname.User'.
    # settings.py
    AUTH_USER_MODEL = 'youappname.User'
     
  • このカスタムモデルをどのように使用するか:たとえば、後でArticleモデルがあり、このUserモデルを外部キーで参照する必要がある場合は、以下の2つの方法で参照できます.1つ目は、Userを現在のファイルに直接インポートすることです.例示的なコードは、
    # models.py
    from django.db import models
    from myauth.models import User
    class Article(models.Model):
        title = models.CharField(max_length=100)
        content = models.TextField()
        author = models.ForeignKey(User, on_delete=models.CASCADE)
    であり、この方法は実行可能である.しかし、より良い使用性のためには、Userを抽象化し、settings.AUTH_USER_MODELを使用して表すことをお勧めします.サンプルコードは、
    # models.py
    from django.db import models
    from django.conf import settings
    class Article(models.Model):
        title = models.CharField(max_length=100)
        content = models.TextField()
        author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    のように、元のUserモデルのテーブル構造を破壊するため、最初のmigrateの前に定義する必要があります.