在Django User模型中需要first_name和last_name

时间:2017-05-13 04:15:44

标签: python django database authentication model

django.contrib.auth.models.User中,first_namelast_name字段都有blank=True。如何在我自己的模型中制作blank=False, null=False

这是我的实现,它基本上遵循Extending the existing User model

的说明
  

models.py

class Fellow(models.Model):

    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE
    )

    first_name = models.CharField(
        _("first_name"),
        max_length=30,
    )
    last_name = models.CharField(
        _("last_name"),
        max_length=30,
    )

    # other fields omitted

from . import signals
  

signals.py

from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

from .models import Fellow


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

但是,在python manage.py shell中进行测试时出现错误:

>>> f = Fellow.objects.create(username='username', password='passwd')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/db/models/query.py", line 392, in create
    obj = self.model(**kwargs)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/db/models/base.py", line 571, in __init__
    raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
TypeError: 'username' is an invalid keyword argument for this function

2 个答案:

答案 0 :(得分:1)

您误解了教程。您要引用的员工示例说明了如何添加到User这是通过OneToOneField完成的,原始User模型保持不变,但出于所有实际目的,它是&#39;好像User有一个名为department的新字段。这是通过在数据库中创建两个单独的表来实现的。

有一点需要注意,在EmployeeFellow中,您无法在未首先创建User实例的情况下以您尝试的方式直接创建新实例。这是因为这些模型都没有直接拥有用户名字段。所以分两步完成

user = User(username='Sun')   
user.set_password('123')
user.save()

f = Fellow(user=user)

但这种方法仍然不太理想。两个模型中都有first_name和last_name字段。它总会导致混乱。正确的方法是继承AbstractBaseUser

class Fellow(AbstractBaseUser):

   first_name = models.CharField(max_length=254)

AbstractBaseUser是一个简单的用户(请参阅代码:https://github.com/django/django/blob/master/django/contrib/auth/base_user.py#L47)它没有first_name和last_name,因此您可以使用所需的行为添加它们。

答案 1 :(得分:0)

您所指的第一行文档

  

有两种方法可以扩展默认用户模型而无需替换您自己的模型

关键字为而不替换

我在这里看到3个选项:

1)从AbstractBaseUser派生用户类并定义所有必填字段。您可以以AbstractUser为例。

2)向UserSerializer或用户保存模型上的pre_save信号添加验证,并验证first_namelast_name字段。最简单的方法,但不是长期项目的好选择。

3)通过将User模型的引用添加为user来执行您选择的方式。定义first_namelast_name但请确保Fellow.first_nameFellow.user.first_name之间没有重复这些字段。这可能很难,因为其他开发者可能会误解这个想法 发生错误是因为尚未创建用户模型,并且启动Fellow实例的正确方法是:

user = User.objects.create(username='test', email='test@example.com')
fellow = Fellow.objects.create(user=user, first_name='firstname', last_name='last_name')