新しい Djnago アプリケーションを構築しています。ログインと登録にdjango-rest-auth ( http://django-rest-auth.readthedocs.io/en/latest/index.html ) を使用しています。ただし、それにはいくつかの問題があります。
正確な問題は次のとおりです。
- ログインの場合: フォームと生データの両方のオプションを使用して API 経由でログインしようとすると、ログインに失敗します。エラーが発生し
"non_field_errors": ["User account is disabled."]
ます。 - 登録の場合: データを入力して登録するとエラーが発生しますが、データはデータベースに保存されます。
今、私はかなりの数のことをしましたが、何が間違っていたのかわかりません。次の順序で物事を行いました
- 新しく作成された Django rest プロジェクト
カスタム ユーザー モデルを持つ myauth というアプリを作成しました。次のようになります。
class UserManager(BaseUserManager): def _create_user(self, username, email, password, is_staff, is_superuser, **extra_fields): now = timezone.now() if not username: raise ValueError(_('The given username must be set')) email = self.normalize_email(email) user = self.model(username=username, email=email, is_staff=is_staff, is_active=False, is_superuser=is_superuser, last_login=now, date_joined=now, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_user(self, username, email=None, password=None, **extra_fields): return self._create_user(username, email, password, False, False, **extra_fields) def create_superuser(self, username, email, password, **extra_fields): user=self._create_user(username, email, password, True, True, **extra_fields) user.is_active=True user.save(using=self._db) return user class User(AbstractBaseUser, PermissionsMixin): username = models.CharField(_('username'), max_length=30, unique=True, help_text=_('Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters'), validators=[ validators.RegexValidator(re.compile('^[\w.@+-]+$'), _('Enter a valid username.'), _('invalid')) ]) first_name = models.CharField(_('first name'), max_length=30, blank=True, null=True) last_name = models.CharField(_('last name'), max_length=30, blank=True, null=True) email = models.EmailField(_('email address'), max_length=255, unique=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=False, 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) receive_newsletter = models.BooleanField(_('receive newsletter'), default=False) birth_date = models.DateField(auto_now=False, null=True) address = models.TextField(max_length=500, null=True) phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.") phone_number = models.CharField(validators=[phone_regex], blank=True, max_length=20) # validators should be a list USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username',] objects = UserManager() class Meta: verbose_name = _('user') verbose_name_plural = _('users') def get_full_name(self): full_name = '%s %s' % (self.first_name, self.last_name) return full_name.strip() def get_short_name(self): return self.first_name def email_user(self, subject, message, from_email=None): send_mail(subject, message, from_email, [self.email])
settings.py as に追加し
AUTH_USER_MODEL = 'myauth.User'
、admin.py にも登録しました。移行により、上記の列を持つすべてのテーブルが作成されました。first_name と last_name をユーザー名と電子メールとパスワードと共に登録できるように登録を変更したいと思いました。また、ユーザー名の代わりに電子メールを使用してログインできるようにしました。そのため、ユーザー モデルと settings.py で衝突するコードが存在する可能性があります。そのために、serializers.py に次のコードを追加しました。
from myauth.models import User from allauth.account import app_settings as allauth_settings from allauth.utils import email_address_exists from allauth.account.adapter import get_adapter from allauth.account.utils import setup_user_email #Custom registration to store first and last name along with email and password class RegisterSerializer(serializers.Serializer): email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED) first_name = serializers.CharField(required=True, write_only=True) last_name = serializers.CharField(required=True, write_only=True) password1 = serializers.CharField(required=True, write_only=True) password2 = serializers.CharField(required=True, write_only=True) def validate_email(self, email): email = get_adapter().clean_email(email) if allauth_settings.UNIQUE_EMAIL: if email and email_address_exists(email): raise serializers.ValidationError( _("A user is already registered with this e-mail address.")) return email def validate_password1(self, password): return get_adapter().clean_password(password) def validate(self, data): if data['password1'] != data['password2']: raise serializers.ValidationError( _("The two password fields didn't match.")) return data def get_cleaned_data(self): return { 'first_name': self.validated_data.get('first_name', ''), 'last_name': self.validated_data.get('last_name', ''), 'password1': self.validated_data.get('password1', ''), 'email': self.validated_data.get('email', ''), } def save(self, request): adapter = get_adapter() user = adapter.new_user(request) self.cleaned_data = self.get_cleaned_data() adapter.save_user(request, user, self) setup_user_email(request, user, []) user.save() return user
私のsettings.pyは次のようになります:
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework.authtoken', 'rest_auth', 'allauth', 'allauth.account', 'rest_auth.registration', 'myauth', 'swarms_app' ) AUTH_USER_MODEL = 'myauth.User' MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', ) ROOT_URLCONF = 'urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], '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 = 'config.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'new_swarms', 'USER': 'root', 'PASSWORD': 'root', 'HOST': 'localhost', # Or an IP Address that your DB is hosted on 'PORT': '3306', } } STATIC_URL = '/static/' ############################################################## ## All the customization as taken from original swarms code ## ############################################################## #This is added to use custon registration serializer which stores first and last name along with email and password REST_AUTH_REGISTER_SERIALIZERS = { 'REGISTER_SERIALIZER': 'myauth.serializers.RegisterSerializer', } REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', ) } #Following is added to enable registration with email instead of username AUTHENTICATION_BACKENDS = ( # Needed to login by username in Django admin, regardless of `allauth` "django.contrib.auth.backends.ModelBackend", # `allauth` specific authentication methods, such as login by e-mail "allauth.account.auth_backends.AuthenticationBackend", ) #This is required otherwise it asks for email server EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' ACCOUNT_AUTHENTICATION_METHOD = 'email' ACCOUNT_EMAIL_REQUIRED = True ACCOUNT_USERNAME_REQUIRED = False
私が作成したカスタムモデルは、移行時に上記のすべてのフィールドを含むテーブルを作成したため、機能しているようです。管理画面でも見ることができます。
ここで何がうまくいかないのですか?