Django-Registration & Django-Profile, используя вашу собственную форму
Я использую django-registration и django-profile для регистрации и профилей. Я хотел бы создать профиль для пользователя во время регистрации. Я создал специальную регистрационную форму и добавил ее в urls.py, используя учебное пособие по:
http://dewful.com/?p=70
Основная идея в учебнике - переопределить регистрационную форму по умолчанию, чтобы создать профиль одновременно.
forms.py - в моих профилях приложение
from django import forms
from registration.forms import RegistrationForm
from django.utils.translation import ugettext_lazy as _
from profiles.models import UserProfile
from registration.models import RegistrationProfile
attrs_dict = { 'class': 'required' }
class UserRegistrationForm(RegistrationForm):
city = forms.CharField(widget=forms.TextInput(attrs=attrs_dict))
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_profile = UserProfile(user=new_user, city=self.cleaned_data['city'])
new_profile.save()
return new_user
В urls.py
from profiles.forms import UserRegistrationForm
и
url(r'^register/$',
register,
{'backend': 'registration.backends.default.DefaultBackend', 'form_class' : UserRegistrationForm},
name='registration_register'),
Отображается форма, и я могу войти в Город, однако она не сохраняет и не создает запись в БД.
Ответы
Ответ 1
Вы на полпути - вы успешно создали настраиваемую форму, которая заменяет форму по умолчанию. Но вы пытаетесь выполнить свою собственную обработку с помощью метода save() в своей модельной форме. Это было возможно в более ранних версиях django-регистрации, но я вижу, что вы указали бэкэнд в своем URL-conf, что используете v0.8.
руководство по обновлению говорит:
Ранее форма, используемая для сбора данные при регистрации ожидались для реализации метода save(), который создаст новую учетную запись пользователя. Это уже не так; создание учетная запись обрабатывается бэкэнд, и поэтому любая пользовательская логика должна быть перешел в пользовательский бэкэнд или подключение слушателей к сигналам отправленных во время процесса регистрации.
Другими словами, метод save() в форме игнорируется теперь, когда вы находитесь на версии 0.8. Вам необходимо выполнить свою собственную обработку либо с помощью пользовательского бэкэнд, либо с помощью сигнала. Я решил создать пользовательский back-end (если кто-то получил эту работу с сигналами, пожалуйста, отправьте код - я не смог заставить его работать таким образом). Вы должны иметь возможность изменить это, чтобы сохранить свой настраиваемый профиль.
- Создайте regbackend.py в своем приложении.
- Скопировать метод register() из DefaultBackend в него.
- В конце метода выполните запрос, чтобы получить соответствующий экземпляр пользователя.
- Сохраните дополнительные поля формы в этом экземпляре.
- Измените URL conf так, чтобы он указывал BOTH пользовательскую форму и пользовательский back-end
Итак, URL conf:
url(r'^accounts/register/$',
register,
{'backend': 'accounts.regbackend.RegBackend','form_class':MM_RegistrationForm},
name='registration_register'
),
regbackend.py имеет необходимый импорт и в основном является копией DefaultBackend с помощью только метода register() и добавления:
u = User.objects.get(username=new_user.username)
u.first_name = kwargs['first_name']
u.last_name = kwargs['last_name']
u.save()
Ответ 2
Как описано в мой комментарий к билету Django Trac Я сделал метакласс и mixin, чтобы разрешить множественное наследование для форм ModelForm
Django. С помощью этого вы можете просто создать форму, которая позволяет одновременно регистрировать поля из моделей пользователей и профилей без полей жесткого кодирования или повторять себя. Используя мой метакласс и mixin (а также mixset mixin), вы можете:
class UserRegistrationForm(metaforms.FieldsetFormMixin, metaforms.ParentsIncludedModelFormMixin, UserCreationForm, UserProfileChangeForm):
error_css_class = 'error'
required_css_class = 'required'
fieldset = UserCreationForm.fieldset + [(
utils_text.capfirst(UserProfileChangeForm.Meta.model._meta.verbose_name), {
'fields': UserProfileChangeForm.base_fields.keys(),
})]
def save(self, commit=True):
# We disable save method as registration backend module should take care of user and user
# profile objects creation and we do not use this form for changing data
assert False
return None
__metaclass__ = metaforms.ParentsIncludedModelFormMetaclass
Где UserCreationForm
может быть, например, форма django.contrib.auth.forms.UserCreationForm
и UserProfileChangeForm
простой ModelForm
для вашей модели профиля. (Не забудьте установить editable
в False
в ваш внешний ключ для модели User
.)
С django-регистрационной базой, имеющей такой метод регистрации:
def register(self, request, **kwargs):
user = super(ProfileBackend, self).register(request, **kwargs)
profile, created = utils.get_profile_model().objects.get_or_create(user=user)
# lambda-object to the rescue
form = lambda: None
form.cleaned_data = kwargs
# First name, last name and e-mail address are stored in user object
forms_models.construct_instance(form, user)
user.save()
# Other fields are stored in user profile object
forms_models.construct_instance(form, profile)
profile.save()
return user
Будьте осторожны, чтобы сигнал регистрации был отправлен в начале этого метода (в методе в суперклассе), а не в конце.
Таким же образом вы можете внести форму изменения как для информации пользователя, так и для профиля. Пример этого вы можете найти в моем комментарии к билету Django Trac, упомянутому выше.
Ответ 3
Решение с сигналами - здесь я написал, как использовать сигналы для сохранения дополнительных данных
Ответ 4
С регистрацией 0,8 и более поздней:
Создайте подкласс register.backends.default.views.RegistrationView в своих views.py или эквиваленте:
from registration.backends.default.views import RegistrationView
class MyRegistrationView(RegistrationView):
form_class= MyCustomRegistrationForm
def register(self, request, **cleaned_data):
new_user= super(MyRegistrationView, self).register(request, **cleaned_data)
# here create your new UserProfile object
return new_user