Как настроить профиль пользователя при использовании django-allauth

У меня есть проект django с приложением django-allauth. Мне нужно собрать дополнительные данные от пользователя при регистрации. Я столкнулся с аналогичным здесь, но, к сожалению, никто не ответил на часть настройки профиля.

Per документация, предоставленная для django-allauth:

ACCOUNT_SIGNUP_FORM_CLASS (= None)

Строка, указывающая на пользовательский класс формы (например, ‘myapp.forms.SignupForm’), который используется во время регистрации, чтобы попросить пользователя ввести дополнительный вход (например, подписка на рассылку новостей, дату рождения). Этот класс должен реализовать метод ‘save’, принимающий нового зарегистрированного пользователя в качестве единственного параметра.

Я новичок в django и борюсь с этим. Может ли кто-нибудь представить пример такого пользовательского класса формы? Нужно ли добавлять класс модели со ссылкой на объект пользователя, например this?

Ответ 1

Предположим, вы хотите спросить пользователя о его первом/последнем имени во время регистрации. Вам нужно будет поместить эти поля в свою форму, например:

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'

Что все.

Ответ 2

Используя решение, предложенное pennersr, я получаю сообщение об изнашивании:

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

Это связано с тем, что с версии 0.15 метод сохранения устарел в пользу метода регистрации регистрации (запроса, пользователя).

Итак, чтобы решить эту проблему, код примера должен выглядеть следующим образом:

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()

Ответ 3

Вот то, что сработало для меня, сочетая несколько других ответов (ни один из них не заполнен на 100% и DRY).

В 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', но это как-то привело к ошибке.

Ответ 4

В 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 по определению полей моделей пользовательских моделей.

Ответ 5

@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()

Ответ 6

Я пробовал много разных учебников, и все они чего-то не хватает, повторяя ненужный код или делая странные вещи, ниже следуют моему решению, которое объединяет все параметры, которые я нашел, он работает, я уже ввел его в но это все еще не убеждает меня, потому что я ожидаю получить 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'

Ответ 7

Создайте модель профиля с пользователем как OneToOneField

class Profile(models.Model):
    user = models.OneToOneField(User, verbose_name=_('user'), related_name='profiles')
    first_name=models.CharField(_("First Name"), max_length=150)
    last_name=models.CharField(_("Last Name"), max_length=150)
    mugshot = ImageField(_('mugshot'), upload_to = upload_to, blank=True)
    phone= models.CharField(_("Phone Number"), max_length=100)
    security_question = models.ForeignKey(SecurityQuestion, related_name='security_question')
    answer=models.CharField(_("Answer"), max_length=200)
    recovery_number= models.CharField(_("Recovery Mobile Number"), max_length=100)
    city=models.ForeignKey(City,related_name='city', blank=True, null=True, help_text=_('Select your City'))
    location=models.ForeignKey(Country,related_name='location', blank=True, null=True, help_text=_('Select your Location'))