Различные пользовательские профили с Django-профилями и Django-регистрацией
-
04-10-2019 - |
Вопрос
Мои модели .py:
USER_TYPES = (
('D', 'Demo' ),
('F', 'Free' ),
('P', 'Premium'),
)
class BaseProfile(models.Model):
user = models.OneToOneField(User, primary_key=True)
user_type = models.CharField(max_length=1, blank=True, choices=USER_TYPES)
class DemoProfile(models.Model):
user = models.OneToOneField(User, primary_key=True)
demo = models.CharField(max_length=10, blank=True)
...
class FreeProfile(models.Model):
user = models.OneToOneField(User, primary_key=True)
free = models.CharField(max_length=10, blank=True)
...
class PremiumProfile(models.Model):
user = models.OneToOneField(User, primary_key=True)
premium = models.CharField(max_length=10, blank=True)
...
class ProxyProfile(BaseProfile):
class Meta:
proxy = True
def get_profile(self):
if self.user_type == 'D':
return DemoProfile._default_manager.get(user__id__exact=self.user_id)
elif self.user_type == 'F':
return FreeProfile._default_manager.get(user__id__exact=self.user_id)
else:
return PremiumProfile._default_manager.get(user__id__exact=self.user_id)
Я использую BaseProfile для отображения user_id к определенному user_type. Я хотел использовать ProxyProfile в качестве прокси, который загружает user_type в зависимости от профилей для модификации, как показано ниже
Содержание моей формы.
class ProfileForm(ModelForm):
...
class Meta:
model = ProxyProfile
exclude = ('user','user_type')
...
ProfileForm предоставляется Django-профили, используя следующий код в URLS.PY:
urlpatterns += patterns('',
url(r'^profiles/edit/', edit_profile,
{'form_class': ProfileForm},
name='profiles_edit_profile'),
(r'^profiles/',include('profiles.urls')),
)
Я также установил в настройках .py:
AUTH_PROFILE_MODULE = 'main.ProxyProfile'
Во время регистрации пользователей все данные БД заполнены правильно (похоже, все в порядке). Я регистрирую, используя форму, переданную Django-регистрацию:
urlpatterns += patterns('',
url(r'^register/$', register,
{'form_class': UserRegistrationForm},
name='registration.views.register'),
(r'', include('registration.urls')),
)
из формы.
class UserRegistrationForm(RegistrationFormUniqueEmail, RegistrationFormTermsOfService):
utype = forms.ChoiceField(choices=USER_CHOICES)
def save(self, profile_callback=None):
new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'],
password.self.cleaned_data['password1'],
email=self.cleaned_data['email'],
)
new_base_profile = BaseProfile(user=new_user, user_type=self.cleaned_data['utype'])
if self.cleaned_data['utype'] == "D":
new_profile = DemoProfile(user=new_user)
if self.cleaned_data['utype'] == "F":
new_profile = FreeProfile(user=new_user)
if self.cleaned_data['utype'] == "P":
new_profile = PremiumProfile(user=new_user)
new_profile.save()
new_base_profile.save()
return new_user
И фаза регистрации работает нормально.
У меня проблема с профилем Редактирование / Детали страницы. Мои профили отфильтрованы в ProxyProfile модели и используются в качестве FormModel в профиле form, не отображаются (я не вижу, что конкретные поля профиля не отображаются на страницу HTML), может быть, есть какой-то другой путь (больше похожего на Django Way :)), чтобы сделать это и рендеринг профиля модели в зависимости от поля user_type, который связан с моделью пользователя).
Заранее спасибо :)
Решение
Хорошо, наконец, у меня была идея, как я могу сделать это :)
В моем моделях .py:
class BaseManager(models.Manager):
def get(self, **kwargs):
self.u = kwargs['user__id__exact']
self.bt = BaseProfile.manager.get(user__id__exact=self.u)
if self.bt.user_type == 'F':
return FreeProfile.objects.get(pk=self.u)
elif self.bt.user_type == 'I':
return PremiumProfile.objects.get(pk=self.u)
else:
return None
class BaseProfile(models.Model):
objects = BaseManager()
manager = UserManager()
user = models.OneToOneField(User, primary_key=True)
user_type = models.CharField(max_length=1, blank=True, choices=USER_TYPES)
class FreeProfile(models.Model):
user = models.OneToOneField(User, primary_key=True)
free = models.CharField(max_length=10, blank=True)
...
class PremiumProfile(models.Model):
user = models.OneToOneField(User, primary_key=True)
premium = models.CharField(max_length=10, blank=True)
...
В Custom Manager - BaseManager I возвращает объект профиля по перезаписанию Meth () методом, используемым Get_Profile. Я должен использовать USERMANAGER по имени просто «менеджер», чтобы предотвратить рекурсивный звонок пользовательского менеджера при назначении Self.Bt
Хорошо, это наполовину пути к достижению того, что я хочу, теперь я могу просматривать разные профили, прикрепленные к пользователям, используя приложение Django-профили.
Далее я хочу использовать модификацию для подготовки формы редактирования для пользовательских профилей. Пользователи могут иметь разные профили, поэтому я применил волшебный трюк, представленный в этом фрагменте: http://djangosnippets.org/snippets/2081/
А теперь в моих формах. Пусть у меня есть:
class FreeForm(forms.ModelForm):
class Meta:
model = FreeProfile
class PremiumForm(forms.ModelForm):
class Meta:
model = PremiumProfile
Далее простые модели моделей для каждого профиля собраны в профиле (
class ProfileForm(ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs['instance'].user
profile_kwargs = kwargs.copy()
profile_kwargs['instance'] = self.user
self.bt = BaseProfile.manager.get(user__id__exact=self.user.id)
if self.bt.user_type == 'F':
self.profile_fields = FreeForm(*args, **profile_kwargs)
elif self.bt.user_type == 'P':
self.profile_fields = PremiumForm(*args, **profile_kwargs)
super(ProfileForm, self).__init__(*args, **kwargs)
self.fields.update(self.profile_fields.fields)
self.initial.update(self.profile_fields.initial)
class Meta:
model = BaseProfile
def save(self):
...
В настройках .py:
AUTH_PROFILE_MODULE = 'main.BaseProfile'
И это работает как очарование, но я задаюсь вопросом, является ли это Django способ достижения поддержки нескольких различных профилей с использованием Django-профилей? Он беспокоит меня, что я должен использовать Get () еще несколько раз, прежде чем представлять детали профиля или формы редактирования.
Но через 4 дня борьба с Джанго, чтобы сделать это, наконец, я могу хорошо спать сегодня вечером :)
Ваше здоровье