自定义Django用户模型

时间:2018-07-07 14:21:57

标签: python django authentication model customization

我只是尝试创建自己的自定义Django用户模型,但是如果我尝试通过前端创建新用户,它将失败:

  

请求方法:POST请求URL:http://127.0.0.1:8000/signup/ Django   版本:2.1b1异常类型:AttributeError异常值:   “经理”对象没有属性“ get_by_natural_key”

首先,我创建了一个新的Django应用"accounts" 然后将以下内容添加到帐户应用程序的models.py中:

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
) 

#User Model Manager
class UserManager(BaseUserManager):
    def create_user(self, username, password=None):
        """
        Creates and saves a User with the given username and password.
        """
        if not username:
            raise ValueError('Error: The User you want to create must have an username, try again')

        user = self.model(
            user=self.normalize_username(username),
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_staffuser(self, username, password):
        """
        Creates and saves a staff user with the given username and password.
        """
        user = self.create_user(
            username,
            password=password,
        )
        user.staff = True
        user.save(using=self._db)
        return user

    def create_superuser(self, username, password):
        """
        Creates and saves a superuser with the given username and password.
        """
        user = self.create_user(
            username,
            password=password,
        )
        user.staff = True
        user.admin = True
        user.save(using=self._db)
        return user


class User(AbstractBaseUser):
    user = models.CharField(
        verbose_name='username',
        max_length=30,
        unique=True,
    )
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False) # a admin user; non super-user
    admin = models.BooleanField(default=False) # a superuser
    # notice the absence of a "Password field", that's built in.

    USERNAME_FIELD = 'user'
    REQUIRED_FIELDS = [] # Username & Password are required by default.

    def get_full_name(self):
        # The user is identified by their Username address
        return self.user

    def get_short_name(self):
        # The user is identified by their Username address
        return self.user
    def __str__(self):              # __unicode__ on Python 2
        return self.user

    def has_perm(self, perm, obj=None):
        """Does the user have a specific permission?"""
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        """Does the user have permissions to view the app `app_label`?"""
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        """Is the user a member of staff?"""
        return self.staff

    @property
    def is_admin(self):
        """Is the user a admin member?"""
        return self.admin

    @property
    def is_active(self):
        """Is the user active?"""
        return self.active
我的实际博客应用的

model.py:

from django.db import models
from django.utils import timezone
from smartfields import fields
from smartfields.dependencies import FileDependency
from smartfields.processors import ImageProcessor

# Categorys of Post Model

class Category(models.Model):
    title = models.CharField(max_length=255, verbose_name="Title")
    description = models.TextField(max_length=1000, null=True, blank=True)
    cover = fields.ImageField(upload_to='categorycovers/', blank=True, null=True, dependencies=[
        FileDependency(processor=ImageProcessor(
            format='JPEG', scale={'max_width': 350, 'max_height': 350}))
    ])
    icon = fields.ImageField(upload_to='categoryicons/', blank=True, null=True, dependencies=[
        FileDependency(processor=ImageProcessor(
            format='JPEG', scale={'max_width': 16, 'max_height': 16}))
    ])

    class Meta:
        verbose_name = "Category"
        verbose_name_plural = "Categories"
        ordering = ['title']

    def __str__(self):
        return self.title

#Post Model
class Post(models.Model):
    author = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
    title = models.CharField(max_length=75)
    content = models.TextField(max_length=10000)
    tag = models.CharField(max_length=50, blank=True)
    category = models.ForeignKey(Category, verbose_name="Category", on_delete=models.CASCADE, null=True)
    postattachment = fields.FileField(upload_to='postattachment/%Y/%m/%d/', blank=True ,null=True)
    postcover = fields.ImageField(upload_to='postcover/%Y/%m/%d/', null=True, dependencies=[
        FileDependency(processor=ImageProcessor(
            format='JPEG', scale={'max_width': 200, 'max_height': 200}))
    ])
    created_date = models.DateField(auto_now_add=True)
    published_date = models.DateField(blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    class Meta:
        ordering = ["-title"]

    def __str__(self):
        return self.title

#Comment(s) of Post Model
class Comment(models.Model):
    author = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
    post=models.ForeignKey(Post, on_delete=models.CASCADE)
    content = models.TextField()
    created_date = models.DateField(default=timezone.now)
    published_date = models.DateField(blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.text

此后,我跳回到settings.py并将自定义用户模型添加到我的实际博客应用程序中:

AUTH_USER_MODEL = 'accounts.User'

我也添加了

INSTALLED_APPS = [
...
    'accounts',
...   
]

我不想为用户提供任何电子邮件地址。我只是简单地只希望通过用户名对它们进行身份验证...

有任何提示吗?谢谢:)

2 个答案:

答案 0 :(得分:1)

Django AbstractBaseUser类没有字段username

在声明中声明一个用户名字段并将其命名为user

但是USERNAME_FIELDusername

像这样更改模型

class User(AbstractBaseUser):
    user = models.CharField(
        verbose_name='username',
        max_length=30,
        unique=True,
    )
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False) # a admin user; non super-user
    admin = models.BooleanField(default=False) # a superuser

    USERNAME_FIELD = 'user'
    REQUIRED_FIELDS = [] # Username & Password are required by default.

    ...

您还可以将用户模型中的用户字段重命名为用户名并解决问题。

答案 1 :(得分:0)

在错误django.core.exceptions.FieldError: Unknown field(s) (username) specified for User中,Django抱怨您的自定义username模型中的未知字段User,您没有username字段,但您声明了USERNAME_FIELD = 'username'

简单的解决方案是将您的user字段重命名为username

如果出于某种原因需要该名称(user,则应将usernameuser中的get_full_name更改为get_short_name,也不要忘记在create_useruser = self.model(user =self.normalize_username(username),)

尝试:

将所有创建的用户重命名为其他名称(例如my_user),因为您必须拖曳两个具有相同名称的变量(USERNAME_FIELD和创建的用户)

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


#User Model Manager
class UserManager(BaseUserManager):
    def create_user(self, user, password=None):
        """
        Creates and saves a User with the given username and password.
        """
        if not user:
            raise ValueError('Error: The User you want to create must have an username, try again')

        my_user = self.model(
            user=self.normalize_username(user),
        )

        my_user.set_password(password)
        my_user.save(using=self._db)
        return my_user

    def create_staffuser(self, user, password):
        """
        Creates and saves a staff user with the given username and password.
        """
        my_user = self.create_user(
            user,
            password=password,
        )
        my_user.staff = True
        my_user.save(using=self._db)
        return my_user

    def create_superuser(self, user, password):
        """
        Creates and saves a superuser with the given username and password.
        """
        my_user = self.create_user(
            user,
            password=password,
        )
        my_user.staff = True
        my_user.admin = True
        my_user.save(using=self._db)
        return my_user


class User(AbstractBaseUser):
    user = models.CharField(
        verbose_name='username',
        max_length=30,
        unique=True,
    )
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False) # a admin user; non super-user
    admin = models.BooleanField(default=False) # a superuser
    # notice the absence of a "Password field", that's built in.

    USERNAME_FIELD = 'user'
    REQUIRED_FIELDS = [] # Username & Password are required by default.

    def get_full_name(self):
        # The user is identified by their Username address
        return self.user

    def get_short_name(self):
        # The user is identified by their Username address
        return self.user    
    def __str__(self):              # __unicode__ on Python 2
        return self.user

    def has_perm(self, perm, obj=None):
        """Does the user have a specific permission?"""
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        """Does the user have permissions to view the app `app_label`?"""
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        """Is the user a member of staff?"""
        return self.staff

    @property
    def is_admin(self):
        """Is the user a admin member?"""
        return self.admin

    @property
    def is_active(self):
        """Is the user active?"""
        return self.active

您的settings.py文件看起来不错。

我希望这会有所帮助。