(編集:Djangoには「プロキシモデル」と呼ばれるまったく別の機能があることを知っています。フィールドをUserProfileに追加できる必要があるため、その機能は役に立ちません。)
だから私は新しいDjangoアプリを開始しています.django.contrib.auth.models.Userの拡張であるUserProfileモデルを作成しており、次のようにUserへの属性リクエストに失敗しました:
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)
User
これは通常は問題なく動作しますが、UserProfileAdmin.list_displayのフィールドを使用しようとすると壊れます。問題は、次の管理者検証コードにあります。
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 クラス自体にはありません。Django シェルでのデモ:
>>> hasattr(UserProfile, 'email')
False
>>> hasattr(UserProfile.objects.all()[0], 'email')
True
掘り下げた後、UserProfile._meta の django.db.models.options.Options.get_field をオーバーライドしたいようです。しかし、これを行うための非ハッキーな方法はないようです (私は現在、UserProfile._meta.[get_field, get_field_by_name] のモンキーパッチを含む非常にハッキーなソリューションを持っています)...何か提案はありますか? ありがとう。