Django-Registration & Django-Profile, используя вашу собственную форму - PullRequest
31 голосов
/ 08 апреля 2010

Я использую 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

In urls.py

from profiles.forms import UserRegistrationForm

и

url(r'^register/$',
                           register,
                           {'backend': 'registration.backends.default.DefaultBackend', 'form_class' : UserRegistrationForm},
                           name='registration_register'),

Форма отображается, и я могу войти в Город, однако он не сохраняет и не создает запись в БД.

Ответы [ 3 ]

29 голосов
/ 22 апреля 2010

Вы на полпути - вы успешно создали пользовательскую форму, которая заменяет форму по умолчанию. Но вы пытаетесь выполнить пользовательскую обработку с помощью метода save () в форме модели. Это было возможно в более старых версиях django-registration, но я могу видеть из того факта, что вы указали в URL-адресе бэкэнд, что вы используете v0.8.

Руководство по обновлению гласит:

Ранее форма использовалась для сбора данные при регистрации ожидались реализовать метод save (), который создаст новую учетную запись пользователя. Это больше не так; создание учетная запись обрабатывается бэкэндом, и поэтому любая пользовательская логика должна быть перешел в пользовательский бэкэнд или подключение слушателей к сигналам отправлено в процессе регистрации.

Другими словами, метод save () в форме игнорируется теперь, когда вы используете версию 0.8. Вам необходимо выполнить пользовательскую обработку либо с пользовательским бэкэндом, либо с сигналом. Я решил создать собственный бэкэнд (если кто-то работал с сигналами, пожалуйста, напишите код - я не смог заставить его работать таким образом). Вы должны иметь возможность изменить это, чтобы сохранить в свой пользовательский профиль.

  1. Создайте regbackend.py в своем приложении.
  2. Скопируйте в него метод register () из DefaultBackend.
  3. В конце метода выполните запрос, чтобы получить соответствующий экземпляр User.
  4. Сохраните дополнительные поля формы в этом экземпляре.
  5. Измените URL-адрес conf так, чтобы он указывал на ОБНУЮ пользовательскую форму И пользовательский бэкэнд

Итак, URL-адрес:

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() 
11 голосов
/ 21 июля 2010

Как описано в моем комментарии к билету Django Trac Я создал метакласс и миксин, чтобы разрешить множественное наследование ModelForm форм Django. При этом вы можете просто создать форму, которая позволяет одновременно регистрировать поля из пользовательских и профильных моделей без жесткого кодирования полей или повторения. Используя мой метакласс и миксин (а также миксин fieldset) вы можете сделать:

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, упомянутому выше.

1 голос
/ 21 мая 2014

С регистрацией 0.8 и позже:

Создайте подкласс registration.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
...