扩展Django 1.11用户模型 [英] Extending the Django 1.11 User Model

查看:71
本文介绍了扩展Django 1.11用户模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试弄清楚如何扩展Django用户模型以向用户添加信息。我似乎无法正常工作。我究竟做错了什么?
可以在我要扩展到的同一模型中使用外键吗?您如何创建超级用户,还是必须通过 python manage.py shell 手动进行操作?

I am attempting to work out how to extend the Django user model to add information to a user. I can't seem to get it to work. What am I doing wrong? Is it okay to have foreignkeys within the same model I am extending in to? How do you create a superuser, or do you have to do it manually through the python manage.py shell?

到目前为止,这是我的代码:

Here's my code so far:

class PersonModel(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    firstName = models.CharField(max_length=50)
    lastName = models.CharField(max_length=50)
    company = models.ForeignKey(CompanyModel, on_delete=models.CASCADE, null=True)
    phone = models.ForeignKey(PhoneModel, on_delete=models.CASCADE, null=True)
    email = models.EmailField(blank=True)

    def __str__(self):
        return '%s %s - %s - %s, %s' % (self.firstName, self.lastName,
                                        self.company, self.phone, self.email
                                       )

    class Meta:
        ordering = ['firstName']
        verbose_name = "Customer Contact Information"
        #verbose_name_plural = "Contacts"

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        PersonModel.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

更新(最终):
在raratiru的帮助下,我我几乎能够得到他共享的脚本。由于我的外键要求,我仍然很难创建一个超级用户。

UPDATE (Final): With the help of raratiru I've been able to mostly get the script he shared going. I still struggle to create a super user because of my foreign key requirements.

from django.contrib.auth.models import (
    AbstractBaseUser,
    PermissionsMixin,
    BaseUserManager,
)
from django.core.mail import send_mail
from django.db import models
from django.utils.translation import ugettext_lazy as _
from customers import models as customers_models

class TravelModel(models.Model):
   mileageRate = models.DecimalField(max_digits=4, decimal_places=3)

   def __str__(self):
      return '%s' % (self.mileageRate)

   class Meta:
      verbose_name = "Current Federal Milage Rate"
      #verbose_name_plural = "Milage"


class UserManager(BaseUserManager):
    def create_user(self, email, firstName, lastName, company, phone, password=None, **kwargs):
        email = self.normalize_email(email)
        user = self.model(email=email, **kwargs)
        user.firstName = firstName
        user.lastName = lastName
        user.company = company
        user.phone = phone
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, firstName, lastName, password=None, **kwargs):
        #user = self.create_user(**kwargs)
        email = self.normalize_email(email)
        user = self.model(email=email, **kwargs)
        user.firstName = firstName
        user.lastName = lastName
        user.set_password(password)
        user.is_superuser = True
        user.is_staff = True
        user.save(using=self._db)
        return user


class AliasField(models.Field):
    def contribute_to_class(self, cls, name, virtual_only=False):
        super().contribute_to_class(cls, name, virtual_only=True)
        setattr(cls, name, self)

    def __get__(self, instance, instance_type=None):
        return getattr(instance, self.db_column)


class MyUser(AbstractBaseUser, PermissionsMixin):
      firstName = models.CharField(max_length=50, blank=False, null=False)
      lastName = models.CharField(max_length=50, blank=False, null=False)
      company = models.ForeignKey(customers_models.CompanyModel, on_delete=models.PROTECT, null=False)
      phone = models.ForeignKey(customers_models.PhoneModel, on_delete=models.PROTECT, null=False)

      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=True,
            help_text=_(
                  'Designates whether this user should be treated as '
                  'active. Unselect this instead of deleting accounts.'
            )
      )
      username = AliasField(db_column='email')

      objects = UserManager()

      USERNAME_FIELD = 'email'
      REQUIRED_FIELDS = ['firstName','lastName',]

      class Meta(object):
            ordering = ['firstName']
            verbose_name = _('Contact')
            verbose_name_plural = _('Contacts')

      def __str__(self):
            return '%s - %s %s - %s - %s' % (self.company, self.firstName, self.lastName, self.email, self.phone)

      def get_full_name(self):
            return self.email

      def get_short_name(self):
            return self.email

      def email_user(self, subject, message, from_email=None, **kwargs):
            """
            Sends an email to this User.
            """
            send_mail(subject, message, from_email, [self.email], **kwargs)

为了规避外键的困扰,最简单的解决方案是在创建之前删除null = False要求超级用户-在之后分配公司和电话-然后将null设置为false。

To circumvent the foreignkey struggles, the easiest solution is to remove the null=False requirement before creating the superuser - assign a company and phone after - and set null back to false afterwards.

推荐答案

这就是我扩展用户的方式模型。以下代码还将用户名替换为电子邮件字段。我发布它是因为它引起核心更改,因此可以弄清楚背后的逻辑。

This is how I extended my user model. The following code also substitutes the username for an email field. I am posting it because it causes core changes so it makes clear the logic behind.

可以在此帖子。也可以在

在这种情况下,AliasField创建字段 username 作为<$的别名c $ c>电子邮件。尽管鉴于django已记录了找到用户模型及其相关字段的正确方法

The AliasField in this case, creates the field username as an alias to email. Although this is not necessary given that django has documented the proper way of finding the user model and its relevant fields.

from django.contrib.auth.models import (
    AbstractBaseUser,
    PermissionsMixin,
    BaseUserManager,
)
from django.core.mail import send_mail
from django.db import models
from django.utils.translation import ugettext_lazy as _


class UserManager(BaseUserManager):
    def create_user(self, email, password=None, **kwargs):
        email = self.normalize_email(email)
        user = self.model(email=email, **kwargs)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, **kwargs):
        user = self.create_user(**kwargs)
        user.is_superuser = True
        user.is_staff = True
        user.save(using=self._db)
        return user


class AliasField(models.Field):
    def contribute_to_class(self, cls, name, private_only=False):
        super().contribute_to_class(cls, name, private_only=True)
        setattr(cls, name, self)

    def __get__(self, instance, instance_type=None):
        return getattr(instance, self.db_column)


class MyUser(AbstractBaseUser, PermissionsMixin):
    custom_field = models.ForeignKey(
        'app.Model',
        on_delete=models.PROTECT,
    )

    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=True,
        help_text=_(
            'Designates whether this user should be treated as '
            'active. Unselect this instead of deleting accounts.'
        )
    )
    username = AliasField(db_column='email')

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['user_branch_key', ]

    class Meta(object):
        ordering = ['email']
        verbose_name = _('My User')
        verbose_name_plural = _('My User')

    def __str__(self):
        return 'id: {0} - {1}, {2}'.format(self.id, self.email, self.user_branch_key)

    def get_full_name(self):
        return self.email

    def get_short_name(self):
        return self.email

    def email_user(self, subject, message, from_email=None, **kwargs):
        """
        Sends an email to this User.
        """
        send_mail(subject, message, from_email, [self.email], **kwargs)

一旦您扩展了用户模型,例如 ./ the_user / models.py 中名称为 the_user 的应用程序,您必须在 settings.py 文件:

Once you extend your user model, for example inside the application with the name the_user in the file ./the_user/models.py you have to make some changes in the settings.py file:


  • 中注册应用程序INSTALLED_APPS

  • ./ manage.py makemigrations && ./ manage.py迁移

  • 设置 AUTH_USER_MODEL ='the_user.MyUser 文档

  • Register the application in the INSTALLED_APPS
  • ./manage.py makemigrations && ./manage.py migrate
  • Set the AUTH_USER_MODEL = 'the_user.MyUser as described in the docs

这样,在另一个模型中,您可以如下添加外键:

This way, in another model you can add a foreignkey as follows:

from the_user.models import MyUser
from django.conf import settings
from django.db import models

class AModel(models.Model)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.PROTECT,
        related_name='%(app_label)s_%(class)s_user'
    )

这篇关于扩展Django 1.11用户模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆