Реализация профиля пользователя через наследование моделей

Сегодня решил в качестве эксперимента пощупать наследование в джанги, которое с относительно недавних пор появилось в trunk.

До этого для реализации профиля я пользовался нескольки брутальным способом: я просто патчил модель пользователя :-) Выглядело это примерно так:


from django.contrib.auth.models import User

new_fields = {
'agency': models.ForeignKey(Agency, blank=True, null=True, verbose_name=u'Агенство', related_name='managers'),
'group': models.CharField(u'Группа', max_length=20, null=True),
}

# Ok, OMG begins!

for name, field in new_fields.iteritems():
User.add_to_class(name, field)

User.get_absolute_url = lambda self: reverse('account.views.user', args=[self.id])
User.get_edit_url = lambda self: reverse('account.views.edit_user', args=[self.id])

Что-то в этом роде :-)

Сегодня я решил поправить OMG и заюзал наследование. Для этого понадобилось сделать три шага:

1) Создать модель UserProfile, унаследовав её от User


class UserProfile(User):
agency = models.ForeignKey(Agency, blank=True, null=True, verbose_name=u'Агенство', related_name='managers')
group = models.CharField(u'Группа', max_length=20, null=True)

get_absolute_url = lambda self: reverse('account.views.user', args=[self.id])
get_edit_url = lambda self: reverse('account.views.edit_user', args=[self.id])


2) Заменить во всём проекте User на UserProfile.

3) Заменить использование ‘django.contrib.auth.middleware.AuthenticationMiddleware’ на самописную account.middleware.AuthenticationMiddleware для того, чтобы в request.user попадал объект UserProfile, а не User


class LazyUser(object):
def __get__(self, request, obj_type=None):
if not hasattr(request, '_cached_user'):
from django.contrib.auth import get_user
from account.models import UserProfile
user = get_user(request)
if user.is_authenticated():
userprofile = UserProfile.objects.get(user_ptr=user)
else:
userprofile = user
request._cached_user = userprofile

return request._cached_user

class AuthenticationMiddleware(object):
def process_request(self, request):
assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
request.__class__.user = LazyUser()
return None


Хм, собственно, всё :-) Я активно ничего не юзал ещё, но пока всё кажется чики-пуки. Если я чего не заметил, плиз, разочаруйте меня :-)
Add post to:   Delicious Reddit Slashdot Digg Technorati Google
Make comment

Comments

вот когда не будет проблем 2 (и более) приложения, расширяющие модель пользователя, состыковать так, чтобы ничего не глючило, тогда и будешь праздновать победу.

Интересно, а можно у наследованной модели указать db_table=”auth_user” и держать все в одной таблице? Или Джанге плохо станет? :))

А мне почему-то манкипатчинг больше нравится :) Хотя это и менее правильно. От лени, видимо.

Required. 30 chars of fewer.

Required.

captcha image Please, enter symbols, which you see on the image