Django自定义用户模型问题

2024-04-23 18:33:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试自定义用户模型(名称:UserProfile),但当我进行迁移时,遇到了一个错误:

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

所以我按照(Manager isn't available; User has been swapped for 'pet.Person')的建议做了一些修改。我把

^{pr2}$

在每个导入自定义用户模型的文件(设置、序列化程序、模型、窗体、管理)中,但这次我收到了另一条错误消息:

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

我怎样才能解决这个问题?在

以下是文件:

在设置.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, } 
 ....

在模型.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') ....

在表单.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

在管理员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)

版本:Django 2.1.1,python 3.6.3


Tags: djangonamefromimportselfauthtruemodel
1条回答
网友
1楼 · 发布于 2024-04-23 18:33:22

自定义User模型时不需要使用User = get_user_model()。我认为您应该继承AbstractUser模型。AbstractUser模型提供用户模型auth.User(包括管理器、权限、验证)所拥有的所有功能。在

相关问题 更多 >