2011-03-06 3 views
1

(편집 : 장고에 "Proxy Models"라는 완전히 다른 기능이 있다는 것을 알고 있습니다.이 기능은 도움이되지 않습니다. 필드를 UserProfile에 추가하십시오.)auth.user 모델 확장, 프록시 필드 및 장고 관리자

그래서 새로운 장고 앱을 시작하고 django.contrib.auth.models.User의 확장이며 다음과 같이 User에 대한 속성 요청을 실패한 UserProfile 모델을 만들고 있습니다. :

from django.db import models 
from django.contrib.auth.models import User 

class UserProfile(models.Model): 
    user = models.OneToOneField(User, related_name='profile') 

    def __getattr__(self, name, *args): 
     if name == 'user' or name == '_user_cache': 
      raise AttributeError(name) 

     try: 
      return getattr(self.user, name, *args) 
     except AttributeError, e: 
      raise AttributeError(name) 

이 일반적으로 잘 작동하지만 휴식은 내가 UserProfileAdmin.list_display에 User 필드를 사용하려고 할 때.

def validate(cls, model): 
    """ 
    Does basic ModelAdmin option validation. Calls custom validation 
    classmethod in the end if it is provided in cls. The signature of the 
    custom validation classmethod should be: def validate(cls, model). 
    """ 
    # Before we can introspect models, they need to be fully loaded so that 
    # inter-relations are set up correctly. We force that here. 
    models.get_apps() 

    opts = model._meta 
    validate_base(cls, model) 

    # list_display 
    if hasattr(cls, 'list_display'): 
     check_isseq(cls, 'list_display', cls.list_display) 
     for idx, field in enumerate(cls.list_display): 
      if not callable(field): 
       if not hasattr(cls, field): 
        if not hasattr(model, field): 
         try: 
          opts.get_field(field) 
         except models.FieldDoesNotExist: 
          raise ImproperlyConfigured("%s.list_display[%d], %r is not a callable or an attribute of %r or found in the model %r." 
           % (cls.__name__, idx, field, cls.__name__, model._meta.object_name)) 

문제는 그 USERPROFILE의 인스턴스가 프록시 필드가 반면, 예를 들어, 다음과 같습니다 문제는 여기에 관리자 유효성 검사 코드에 이메일을 보내면 UserProfile 클래스 자체는 그렇지 않습니다. 장고 쉘에서 시연 :

>>> hasattr(UserProfile, 'email') 
False 
>>> hasattr(UserProfile.objects.all()[0], 'email') 
True 

을 뒷조사 한 후, 내가 UserProfile._meta에 대한 django.db.models.options.Options.get_field를 오버라이드 (override) 할 것 같다. 하지만이 일을 해커가 아닌 방법으로 보이지 않습니다. (필자는 현재 매우 익숙한 해결책을 가지고 있습니다. 여기에는 원숭이 패치 UserProfile._meta가 포함됩니다. [get_field, get_field_by_name]) ... 제안 사항이 있습니까? 감사.

+0

해킹 된 솔루션이 있음을 알리기 위해 업데이트되었습니다. 그러나 해키가 아닌 사람이 있으면 위대 할 것입니다. – rfrankel

+0

아, 그건 그렇고, 우리에게'admin.py' 파일을 보여 주면 유용 할 수 있습니다. = P –

답변

0

이것은 프록시 클래스가 아니며, 관계입니다. 당신이 당신 UserProfileAdmin에 list_display에있을 사용자에서 필드를 원하는 경우 Meta.proxy = True

+0

네, 제목을 업데이트했습니다. 정확히 혼동을 일으킬 수 있다는 것을 깨달았 기 때문에 방금 제목을 업데이트했습니다. 나는 "Proxy Models"가 다른 점을 알고 있지만 UserProfile에 필드를 추가 할 수 있기를 원하기 때문에이 경우에는 도움이되지 않습니다. 그래서 내 제목이 더 분명 할 수있는 동안 내 질문이 나타납니다. – rfrankel

0

로 원래 모델의 하위 클래스 이상에 Proxy Model들, 참조하십시오 : 당신이 원하는 경우

class UserProfileAdmin(admin.ModelAdmin): 
    list_display = ('user__email',) 

양식의 일부로 사용하려면 추가 필드로 UserProfileForm에 추가하고 양식에서 유효성을 검사하십시오.

+1

고마워,하지만 사실은 적어도 장고 1.2.5에서 작동하지 않는 list_display에서 필드 조회를 사용합니다. – rfrankel

2

간단하게 유지하십시오. 다음은 우리가 사용하는 라이브러리의 UserProfile 모델의 예입니다.

class UserProfile(models.Model): 
    user = models.OneToOneField(User) 
    accountcode = models.PositiveIntegerField(null=True, blank=True) 

그게 전부입니다. __getattr__ 무시로 귀찮게하지 마십시오. 대신 관리자 인터페이스를 사용자 정의 :이 인라인으로 사용자 프로필에 액세스 할 수있는, 당신은 User 객체를 CRUD 할 수 있습니다

from django.contrib.auth.admin import UserAdmin 
from django.contrib.auth.models import User 

class UserProfileInline(admin.StackedInline): 
    model = UserProfile 

class StaffAdmin(UserAdmin): 
    inlines = [UserProfileInline] 
    # provide further customisations here 

admin.site.register(User, StaffAdmin) 

. 이제 UserProfile에서 User 모델로 프록시 속성 조회를 할 필요가 없습니다. User u의 에 액세스하려면 u.get_profile()

+0

get_profile()을 작동 시키려면 settings.py에서 AUTH_PROFILE_MODULE 설정을 올바른 모델로 설정해야합니다. – Cromulent

+0

감사합니다. 관리자 문제는 해결되지만 프로파일의 사용자 속성에 액세스 할 때마다 성가신 여분의'.user '를 처리해야합니다.저는'profile.user.X' 나'user.get_profile() .Y' 같은 것들을 끊임없이하고있는 또 다른 코드베이스를 가지고 있습니다.이 새로운 코드베이스에서, 한 곳에서 약간의'__getattr__' 추함이 가치 있다고 생각합니다 증가 된 일관성. 그 밖의 것이 없다면 개발 중에 생산성이 증가 할 것입니다. – rfrankel

+1

어쨌든 사용자 개체에는 필드가 몇 개만 있습니다. 사용자에게 위임 한 userprofile에 @properties를 정의하면됩니다. 어떤 이유로 든'__getattr__' 메소드가 마음에 들지 않습니다. –

관련 문제