2017-05-13 41 views
1

django.contrib.auth.models.User中,first_namelast_name字段都有blank=True。我怎樣才能使他們在我自己的模型blank=False, null=False在Django中需要first_name和last_name用戶模型

這裏是我的實現,基本上遵循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 
+0

您應該從原始用戶類派生您的模型。 –

+0

@KlausD。你的意思是直接繼承'User'嗎?但是文檔中的示例代碼寫入'Employee Employee(models.Model):'而不是'Employee Employee(用戶):'... –

+0

@KlausD。這樣做會給我一個錯誤:'django.core.exceptions.FieldError:'Fellow'類中的本地字段'first_name'與基類'User'中的同名字段發生衝突。 –

回答

1

你誤會了教程。您所指的員工示例說明了如何添加到User,這是通過OneToOneField完成的,該模式保留原始User模型完好無損,但出於所有實際目的,就好像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和姓氏,所以你可以用你想要的行爲進行添加。

0

v你指的是文檔的紅黴素第一行說

There are two ways to extend the default User model without substituting your own model

的關鍵詞是無取代的

我看到三個選項,在這裏:

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='[email protected]') 
fellow = Fellow.objects.create(user=user, first_name='firstname', last_name='last_name') 
相關問題