web-dev-qa-db-ja.com

Django-Registration&Django-Profile、独自のカスタムフォームを使用

私はDjango-registrationとDjango-profileを使用して、登録とプロファイルを処理しています。登録時にユーザーのプロファイルを作成したいと思います。カスタム登録フォームを作成し、次のチュートリアルを使用してurls.pyに追加しました。

http://dewful.com/?p=7

チュートリアルの基本的な考え方は、デフォルトの登録フォームをオーバーライドして、同時にプロファイルを作成することです。

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'),

フォームが表示され、Cityに入力できますが、DBにエントリが保存または作成されません。

31
ismail

これで途中です-デフォルトのフォームを置き換えるカスタムフォームが正常に作成されました。ただし、モデルフォームのsave()メソッドを使用してカスタム処理を実行しようとしています。これは古いバージョンのDjango-registrationで可能でしたが、URL confでバックエンドを指定したことから、v0.8を使用していることがわかります。

アップグレードガイド はこう言っています:

以前は、登録時にデータを収集するために使用されるフォームは、新しいユーザーアカウントを作成するsave()メソッドを実装すると想定されていました。これはもう当てはまりません。アカウントの作成はバックエンドによって処理されるため、カスタムロジックはカスタムバックエンドに移動するか、リスナーを登録プロセス中に送信された信号に接続する必要があります。

つまり、バージョン0.8を使用しているため、フォームのsave()メソッドは無視されます。カスタムバックエンドまたはシグナルを使用してカスタム処理を行う必要があります。私はカスタムバックエンドを作成することを選択しました(シグナルでこれを機能させる人がいる場合は、コードを投稿してください-そのように機能させることができませんでした)。これを変更して、カスタムプロファイルに保存できます。

  1. アプリにregbackend.pyを作成します。
  2. Register()メソッドをDefaultBackendからそれにコピーします。
  3. メソッドの最後で、クエリを実行して、対応するUserインスタンスを取得します。
  4. 追加のフォームフィールドをそのインスタンスに保存します。
  5. カスタムフォームとカスタムバックエンドの両方を指すようにURL設定を変更します

したがって、URL confは次のとおりです。

url(r'^accounts/register/$',
    register,
    {'backend': 'accounts.regbackend.RegBackend','form_class':MM_RegistrationForm},        
    name='registration_register'
    ),

regbackend.pyには必要なインポートがあり、基本的にはregister()メソッドのみを追加したDefaultBackendのコピーであり、以下が追加されています。

    u = User.objects.get(username=new_user.username)
    u.first_name = kwargs['first_name']
    u.last_name = kwargs['last_name']
    u.save() 
29
shacker

Django Tracチケットに関するコメント で説明したように、ModelForm Djangoフォームの多重継承を可能にするために、メタクラスとミックスインを作成しました。これを使用すると、フィールドをハードコーディングしたり繰り返したりせずに、ユーザーモデルとプロファイルモデルのフィールドを同時に登録できるフォームを簡単に作成できます。私のメタクラスとミックスイン(およびフィールドセットミックスイン)を使用すると、次のことができます。

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モデルへの外部キーでFalseUserに設定することを忘れないでください。)

Django-registrationバックエンドにそのような登録メソッドがある場合:

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チケットに関する私のコメントにあります。

11
Mitar

登録0.8以降:

Views.pyまたは同等のものに、registration.backends.default.views.RegistrationViewのサブクラスを作成します。

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
1
tzot