web-dev-qa-db-ja.com

Django-allauthを使用するときにユーザープロファイルをカスタマイズする方法

Django-allauthアプリを使用したDjangoプロジェクトがあります。サインアップ時にユーザーから追加のデータを収集する必要があります。同様の 質問 が、プロファイルのカスタマイズ部分には誰も回答しませんでした。

Django-allauthに提供されるドキュメント ごと:

ACCOUNT_SIGNUP_FORM_CLASS(= None

ユーザーに追加入力(ニュースレターのサインアップ、生年月日など)を求めるためにサインアップ中に使用されるカスタムフォームクラス(例:‘myapp.forms.SignupForm’)を指す文字列。このクラスは‘save’メソッドを実装し、新しくサインアップしたユーザーを唯一のパラメーターとして受け入れます。

Djangoが初めてで、これに苦労しています。誰かがこのようなカスタムフォームクラスの例を提供できますか?モデルクラスを追加する必要がありますか? this

98
Shreyas

サインアップ中にユーザーに姓/名を尋ねたいとします。次のように、これらのフィールドを独自のフォームに配置する必要があります。

class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='Voornaam')
    last_name = forms.CharField(max_length=30, label='Achternaam')

    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.save()

次に、設定で次のフォームをポイントします。

ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm'

それで全部です。

156
pennersr

Pennersrによって提案されたソリューションを使用して、DeprecationWarningを取得していました:

DeprecationWarning: The custom signup form must offer a def signup(self, request, user) method DeprecationWarning)

これは、 バージョン0.15以降 def signup(request、user)メソッドを支持してsaveメソッドが推奨されなくなったためです。

これを解決するには、例のコードは次のようになります。

class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='Voornaam')
    last_name = forms.CharField(max_length=30, label='Achternaam')

    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.save()
22
ferrangb

ここに、他のいくつかの答えを組み合わせたものがあります(100%完全で乾燥しているものはありません)。

yourapp/forms.py

from Django.contrib.auth import get_user_model
from Django import forms

class SignupForm(forms.ModelForm):
    class Meta:
        model = get_user_model()
        fields = ['first_name', 'last_name']

    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.save()

settings.py

ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.SignupForm'

このように、DRYになるようにモデルフォームを使用し、新しいdef signup'myproject.myapp.forms.SignupForm'しかし、それは何らかの形でエラーになりました。

15
Howardwlo

@Shreyas:以下の解決策は最もクリーンではないかもしれませんが、うまくいきます。さらにクリーンアップするための提案があれば教えてください。

デフォルトのユーザープロファイルに属さない情報を追加するには、まずyourapp/models.pyにモデルを作成します。一般的なDjangoのドキュメントを読んで詳細を確認してください。ただし、基本的には:

from Django.db import models

class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='profile')
    organisation = models.CharField(organisation, max_length=100, blank=True)

次に、yourapp/forms.pyにフォームを作成します。

from Django import forms

class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='Voornaam')
    last_name = forms.CharField(max_length=30, label='Achternaam')
    organisation = forms.CharField(max_length=20, label='organisation')

    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        # Replace 'profile' below with the related_name on the OneToOneField linking back to the User model
        up = user.profile
        up.organisation = self.cleaned_data['organisation']
        user.save()
        up.save()
5
mark

あなたのusers/forms.py あなたが置く:

from Django.contrib.auth import get_user_model
class SignupForm(forms.ModelForm):
    class Meta:
        model = get_user_model()
        fields = ['first_name', 'last_name']
    def save(self, user):
        user.save()

Settings.pyに以下を置きます:

ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.SignupForm'

この方法で、DRY多重度による原則ユーザーモデルフィールド定義を破ることはありません。

4
Adam Dobrawy

私は多くの異なるチュートリアルを試してみましたが、それらのすべてが何かを失い、不必要なコードを繰り返したり、奇妙なことをしたりします。私が見つけたすべてのオプションを結合するソリューションに従ってくださいユーザーに作成した関数内でfirst_nameとlast_nameを受け取り、フォーム内でプロファイルを作成しないようにすることを期待しているため、まだ納得できません。

Models.py

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    nationality = models.CharField(max_length=2, choices=COUNTRIES)
    gender = models.CharField(max_length=1, choices=GENDERS)

def __str__(self):
    return self.user.first_name


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

Forms.py

class SignupForm(forms.ModelForm):
    first_name = forms.CharField(max_length=100)
    last_name = forms.CharField(max_length=100)

    class Meta:
        model = Profile
        fields = ('first_name', 'last_name', 'nationality', 'gender')

    def signup(self, request, user):
        # Save your user
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.save()

        user.profile.nationality = self.cleaned_data['nationality']
        user.profile.gender = self.cleaned_data['gender']
        user.profile.save()

Settings.py

ACCOUNT_SIGNUP_FORM_CLASS = 'apps.profile.forms.SignupForm'
4
Gregory