Реализация профиля пользователя через наследование моделей
Сегодня решил в качестве эксперимента пощупать наследование в джанги, которое с относительно недавних пор появилось в trunk.
До этого для реализации профиля я пользовался нескольки брутальным способом: я просто патчил модель пользователя :-) Выглядело это примерно так:
Что-то в этом роде :-)
Сегодня я решил поправить OMG и заюзал наследование. Для этого понадобилось сделать три шага:
1) Создать модель UserProfile, унаследовав её от User
2) Заменить во всём проекте User на UserProfile.
3) Заменить использование ‘django.contrib.auth.middleware.AuthenticationMiddleware’ на самописную account.middleware.AuthenticationMiddleware для того, чтобы в request.user попадал объект UserProfile, а не User
Хм, собственно, всё :-) Я активно ничего не юзал ещё, но пока всё кажется чики-пуки. Если я чего не заметил, плиз, разочаруйте меня :-)
До этого для реализации профиля я пользовался нескольки брутальным способом: я просто патчил модель пользователя :-) Выглядело это примерно так:
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
Хм, собственно, всё :-) Я активно ничего не юзал ещё, но пока всё кажется чики-пуки. Если я чего не заметил, плиз, разочаруйте меня :-)






Comments
вот когда не будет проблем 2 (и более) приложения, расширяющие модель пользователя, состыковать так, чтобы ничего не глючило, тогда и будешь праздновать победу.
Интересно, а можно у наследованной модели указать db_table=”auth_user” и держать все в одной таблице? Или Джанге плохо станет? :))
А мне почему-то манкипатчинг больше нравится :) Хотя это и менее правильно. От лени, видимо.