2

自分の登録フォームを含めるようにDjango登録を拡張しようとしています。原則として、これはかなり簡単です。CustomRegistrationForm元のフォーム( )の子である独自のフォーム()を作成するだけRegistrationFormです。次に、django登録のuser_registeredシグナルを使用して、特定の入力を処理できます。

これが私がしたことです:

urls.py:

from django.conf.urls import patterns, include, url
from registration.views import register
from forms import CustomRegistrationForm
from django.contrib import admin
import regbackend
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^register/$', register, {'backend': 'registration.backends.default.DefaultBackend', 'form_class': CustomRegistrationForm, 'template_name': 'custom_profile/registration_form.html'}, 
                        name='registration_register'),
)

regbackend.py:

from django import forms
from models import UserProfile
from forms import CustomRegistrationForm

def user_created(sender, user, request, **kwargs):
    form = CustomRegistrationForm(data=request.POST, files=request.FILES)
    if form.is_valid(): # HERE: always fails
        user_profile = UserProfile()
        user_profile.user = user
        user_profile.matriculation_number = form.cleaned_data['matriculation_number']
        user_profile.save()

from registration.signals import user_registered
user_registered.connect(user_created)

forms.py:

from models import UserProfile
from django import forms
from registration.forms import RegistrationForm
from django.utils.translation import ugettext_lazy as _

attrs_dict = {'class': 'required'}

class CustomRegistrationForm(RegistrationForm):
    matriculation_number = forms.CharField(widget=forms.TextInput(attrs=attrs_dict),
                                           label=_("Matriculation number"),
                                           max_length=12,
                                           error_messages={'invalid': _("This value has to be unique and may contain only numbers.")},
                                           initial=108)

    def clean_matriculation_number(self):
        print "Validating matriculation number."
        data = self.cleaned_data['matriculation_number']
        if len(data) != 12:
            raise forms.ValidationError(_("Matriculation number consists of exactly 12 digits."))
        return data

したがって、問題はis_valid()関数です。これは、常に。を返す​​ためFalseです。エラーがなくても!では、何が問題なのですか?私はこれに何時間も費やしました、そして私はもうわかりません:(

どんな助けでも大歓迎です!!

4

2 に答える 2

2

失敗する理由form.is_valid()は、フォームの "clean_username" 関数が、渡されたユーザー名が既に存在するかどうかをチェックするためと考えられます。User オブジェクトが作成されてデータベースに追加された後にシグナルが送信されるため、フォームは毎回このテストに合格しません。私の推測では、 return のform.cleaned_data後にログインすると、ユーザー名を除くすべてのフィールドのリストが表示されis_valid()ます。False

form.dataフォーム clean_ 関数が変更を加えた場合、フィールドの変更された値が含まれていない可能性があります (form.data に関するドキュメントはあまり見つかりませんでした)。

これが引き起こす可能性のある潜在的な問題を回避するために、カスタム登録フォーム用に 2 つのクラスを作成しました。

# I use this one for validating in my create_user_profile function
class MyRegistrationFormInternal(forms.Form):
    # Just an example with only one field that holds a name
    name = forms.CharField(initial="Your name", max_length=100)    
    def clean_name(self):
        # (Optional) Change the name in some way, but do not check to see if it already exists
        return self.cleaned_data['name'] + ' foo '
# This one is actually displayed
class MyRegistrationForm (MyRegistrationFormInternal):
    # Here is where we check if the user already exists
    def clean_name(self):
        modified_name = super(MyRegistrationForm, self).clean_name()
        # Check if a user with this name already exists
        duplicate = (User.objects.filter(name=modified_name)
        if duplicate.exists():
            raise forms.ValidationError("A user with that name already exists.")  
        else:
            return modified_name

次に、form.data (いくつかの点でまだ「汚れている」可能性があります) を使用する代わりに、POST データを を介して実行でき、常に false を返すMyRegistrationFormInternalis_valid()は限りません。

これが最もクリーンなソリューションではないことはわかっていますが、(おそらく生の) form.data を使用する必要がなくなります。

于 2013-08-21T21:56:35.210 に答える
1

わかりました(多かれ少なかれ)解決したと思います。

なぜフォームが検証されなかったのか、まだよくわかりません。しかし、私が言ったように、私は django-registration を拡張し、「登録」ビューはすでにフォームの is_valid() を呼び出しているので、投稿されたデータをさらに処理するときにフォームが有効であると想定できます。次に、ビューはバックエンドを呼び出します

backend.register(request, **form.cleaned_data)

リクエストと消去されたデータ (ユーザー名、電子メール、パスワードのみ) と共に。追加情報が不足しているため、登録に使用できません。次に、バックエンドは私が使用しているシグナルを発生させます。私がしたことは、提供されたリクエストでフォームを再度作成したことです。ただし、このフォームは検証されません (そして、私はすべてを試しました!!) 調べました。django-registration とまったく同じことを行っていますが、私のコードでは機能していません。

フォームがまだ検証されていないため、実際には問題を解決できませんでした。しかし、フォームが「登録」ビューによってすでに検証されていることに気付いたとき、これで安心しました。だから私は form.cleaned_data[..] の代わりに form.data[..] を使用していますが、これは問題ではありません...

于 2013-01-19T12:52:47.077 に答える