简体   繁体   English

Django自定义用户模型问题

[英]Django custom user model issue

I am trying to customize user model (name: UserProfile) but when I did makemigrations I got an error: 我正在尝试自定义用户模型(名称:UserProfile),但是在进行makemigrations时出现错误:

AttributeError: Manager isn't available; 'auth.User' has been swapped for 'accounts.UserProfile'

so I follow the suggestion from ( Manager isn't available; User has been swapped for 'pet.Person' ) and made some changes. 因此我遵循( 管理器不可用;用户已换成'pet.Person' )的建议,并进行了一些更改。 I put 我放

from django.contrib.auth import get_user_model
User = get_user_model()

in every files which custom user model imported (settings, serializers, model, forms, admin) but this time I got another error message: 在自定义用户模型导入的每个文件中(设置,序列化器,模型,表单,管理),但是这次我收到了另一条错误消息:

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

How can I fix this problem? 我该如何解决这个问题?

Here are files: 这些是文件:

settings.py settings.py

> import os import datetime from django.conf import settings
> 
> 
> # 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.1/howto/deployment/checklist/
> 
> # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'ruho^096p16m=vg!sn(&o46-qwe#y(zf^bee&!wujo-4h@%hgl'
> 
> # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True
> 
> ALLOWED_HOSTS = ['*']
> 
> 
> # Application definition INSTALLED_APPS = [
>     'rest_framework', # Django rest framework 套件
>     'rest_framework.authtoken',
>     'grappelli', # grappelli admin 版面套件
>     'django.contrib.admin',
>     'django.contrib.auth',
>     'django.contrib.contenttypes',
>     'django.contrib.sessions',
>     'django.contrib.messages',
>     'django.contrib.staticfiles',
>     'django.contrib.sites',
>     'rest_auth',
>     'rest_auth.registration',
>     'debug_toolbar', # django debug 工具列
>     'django_extensions', # django 擴展套件,提供一些cli指令
>     'import_export', # 可從 admin 匯出資料 (目前因版本關係,所以無法使用)
>     'django_filters', # 優化從model query 資料效能
>     'allauth', # django allauth 套件
>     'allauth.account', # django allauth 套件
>     'allauth.socialaccount',  # django allauth 套件
>     'allauth.socialaccount.providers.facebook',  # django allauth 套件,設定使用FB登入用
>     # 'rest_framework_docs', # 可輸出API文件 (目前因版本關係,所以無法使用)
>     'books', # 書籍APP
>     'accounts',# 使用者帳號APP ]
> 
> from django.contrib.auth import get_user_model 
  User = get_user_model()
> 
> AUTH_USER_MODEL = 'accounts.UserProfile'
> 
> 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',
>     'debug_toolbar.middleware.DebugToolbarMiddleware', ]
> 
> INTERNAL_IPS = ('127.0.0.1',)
> 
> # 配置django_rest_framework REST_FRAMEWORK = {
>     # Use Django's standard `django.contrib.auth` permissions,
>     # or allow read-only access for unauthenticated users.
>     'DEFAULT_AUTHENTICATION_CLASSES': (
>         'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
>         'rest_framework.authentication.SessionAuthentication',
>         'rest_framework.authentication.BasicAuthentication',
>     ),
>     'DEFAULT_PERMISSION_CLASSES': [
>         'rest_framework.permissions.IsAuthenticated',
>     ] }
> 
> # 配置JQuery和SHOW_TOOLBAR_​​CALLBACK DEBUG_TOOLBAR_CONFIG = {
>     'JQUERY_URL': 'https://ajax.googleapis.com/ajax/libs/dojo/1.13.0/dojo/dojo.js',
>     'SHOW_TOOLBAR_​​CALLBACK': lambda request: DEBUG, } 
 ....

model.py model.py

from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from books.models import Bookinfo
from datetime import datetime, timedelta
import jwt

from django.contrib.auth import get_user_model
User = get_user_model()


# 建立usermanager定義使用者和高級使用者instance作為數據查詢的管理器
class UserManager(BaseUserManager):

    # 建立一般使用者
    def create_user(self, username, email, password=None):

        # 判斷使用者是否有輸入使用者名稱和email
        if username is None:
            raise TypeError('請填入使用者名稱')
        if email is None:
            raise TypeError('請填入Email')

        user = self.model(
            username=username,
            email=self.normalize_email(email)
        )
        user.set_password(password)
        user.save()

        return user

    # 建立高級使用者
    def create_superuser(self, username, email, password):

        if password is None:
            raise TypeError('Superusers must have a password')

        # 直接使用建立一般使用者方法
        user = self.create_user(username, email, password)
        user.is_superuser = True
        user.is_staff = True
        user.save()

        return user

# 定義使用者資料表
class UserProfile(AbstractBaseUser, PermissionsMixin):

    class Meta:
        db_table = 'userprofile'

    # 定義使用者需填入資料
    username = models.CharField(max_length=255, db_index=True, unique=True, verbose_name='用戶名')
    user_image = models.ImageField(upload_to='img', verbose_name='用戶圖片')
    email = models.EmailField(db_index=True, unique=True, verbose_name='電子郵件')
    birthday = models.DateField(verbose_name='生日')
    GENDER_CHOICES = (
        ('Male', '男'), 
        ('Female', '女')
    )
    gender = models.CharField(
        max_length=5, choices=GENDER_CHOICES, verbose_name='性別')
    location = models.CharField(max_length=255, blank=True, verbose_name='地區')
    about = models.TextField(blank=True, verbose_name='關於我')

    # 確認使用者是否還有再使用平台
    is_active = models.BooleanField(default=True)
    # 確認使用者是否為管理者
    is_staff = models.BooleanField(default=False)

    # 創建時間 
    create_at = models.DateTimeField(auto_now_add=True)
    # 更新資料時間
    update_at = models.DateTimeField(auto_now=True)

    # 外鍵:將評論和書櫃關聯起來
    com = models.OneToOneField(
         'Comments', null=True, blank=True, on_delete=models.CASCADE, verbose_name='評論ID')
    bookshelf = models.OneToOneField(
         'bookshelf', null=True, blank=True, on_delete=models.CASCADE, verbose_name='書櫃ID')

    # The `USERNAME_FIELD` property tells us which field we will use to log in.
    # In this case we want it to be the email field.
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    # Tells Django that the UserManager class defined above should manage
    # objects of this type.
    objects = UserManager()

    def __str__(self):
        """
        Returns a string representation of this `User`.

        This string is used when a `User` is printed in the console.
        """
        return self.email

    @property
    def token(self):
        """
        Allows us to get a user's token by calling `user.token` instead of
        `user.generate_jwt_token().

        The `@property` decorator above makes this possible. `token` is called
        a "dynamic property".
        """
        return self._generate_jwt_token()

    def get_full_name(self):
        """
        This method is required by Django for things like handling emails.
        Typically this would be the user's first and last name. Since we do
        not store the user's real name, we return their username instead.
        """
        return self.username

    def get_short_name(self):
        """
        This method is required by Django for things like handling emails.
        Typically, this would be the user's first name. Since we do not store
        the user's real name, we return their username instead.
        """
        return self.username

    def _generate_jwt_token(self):
        """
        Generates a JSON Web Token that stores this user's ID and has an expiry
        date set to 60 days into the future.
        """
        dt = datetime.now() + timedelta(days=60)

        token = jwt.encode({
            'id': self.pk,
            'exp': int(dt.strftime('%s'))
        }, settings.SECRET_KEY, algorithm='HS256')

        return token.decode('utf-8') ....

form.py form.py

from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import UserProfile

from django.contrib.auth import get_user_model
User = get_user_model()

class UserProfileForm(UserCreationForm):
    class Meta:
        model = UserProfile
        fields = (
            'username', 'user_image', 'email', 'gender',
            'birthday', 'location', 'about' 
        )


class UserProfileChangeForm(UserChangeForm):
    class Meta:
        model = UserProfile
        fields = UserChangeForm.Meta.fields

admin.py admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Comments, Bookshelf, UserProfile
from import_export.admin import ImportExportModelAdmin
from .forms import UserCreationForm, UserChangeForm

from django.contrib.auth import get_user_model
User = get_user_model()

class UserProfileAdmin(UserAdmin):
    add_form = UserCreationForm
    form = UserChangeForm
    model = UserProfile
    list_display = ('_id', 'user_name', 'e-mail', 'gender',
                    'birthday', 'location', 'created_at')
    search_fields = ['user_name', 'gender']

class CommentsAdmin(ImportExportModelAdmin):
    list_display = ('_id', 'rating', 'read_status', 'created_time')
    search_fields = ['rating']

class BookshelfAdmin(ImportExportModelAdmin):
    list_display = ('_id', 'created_time')
    # search_fields = ['gender']


admin.site.register(UserProfile, UserProfileAdmin)
admin.site.register(Comments, CommentsAdmin)
admin.site.register(Bookshelf, BookshelfAdmin)

version: Django 2.1.1, python 3.6.3 版本:Django 2.1.1,python 3.6.3

User = get_user_model() is not required to use when you customized User model. 自定义User模型时,无需使用User = get_user_model() I think you should inherit from AbstractUser model. 我认为您应该继承AbstractUser模型。 AbstractUser model provides all which user model auth.User (including mangers, permissions, validations) has. AbstractUser模型提供auth.User (包括管理器,权限,验证)具有的所有用户模型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM