2017-05-13 1 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의 지침을 다음과 내 구현입니다 : python manage.py shell에서 테스트 할 때 그러나

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) 

, 오류가 발생했습니다 :

>>> 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

원래 User 클래스에서 모델을 파생해야합니다. –

+0

@KlausD. 'User'를 서브 클래 싱하는 것이 무엇입니까? 그러나 문서의 예제 코드는'class Employee (User) :'... 대신에'class Employee (models.Model) :'을 작성합니다 ... –

+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 필드가 있습니다. 그것은 항상 혼란을 가져올 것입니다.당신은 당신이 원하는 행동을 추가 할 수 있도록 그것은 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 코드 참조) 하위 클래스입니다.

0

v

1) AbstractBaseUser에서 당신에게 사용자 클래스를 파생하고 필요한 모든 정의 : 당신이 언급하는 문서 ERY 첫 번째 줄은 내가 여기에 3 가지 옵션이 볼

을 대체하지 않고 키워드가 입니다

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

말한다 전지. 예를 들어 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') 
관련 문제