Как настроить профиль пользователя при использовании django-allauth
У меня есть проект django с приложением django-allauth. Мне нужно собрать дополнительные данные от пользователя при регистрации. Я сталкивался с подобным вопросом здесь, но, к сожалению, никто не ответил на часть настройки профиля.
Согласно документации, предоставленной дляdjango-allauth
:
ACCOUNT_SIGNUP_FORM_CLASS
знак равноNone
)Строка, указывающая на пользовательский класс формы (например,
‘myapp.forms.SignupForm’
), который используется во время регистрации, чтобы запросить у пользователя дополнительные данные (например, подписка на новостную рассылку, дату рождения). Этот класс должен реализовывать‘save’
метод, принимая вновь зарегистрированного пользователя в качестве единственного параметра.
Я новичок в Django и борюсь с этим. Может кто-нибудь привести пример такого пользовательского класса формы? Нужно ли также добавить класс модели со ссылкой на объект пользователя, как это?
7 ответов
Предположим, вы хотите спросить пользователя его имя / фамилию во время регистрации. Вам нужно будет поместить эти поля в свою собственную форму, например так:
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'
Это все.
Используя решение, предложенное pennersr, я получил предупреждение об устаревании:
DeprecationWarning: The custom signup form must offer a def signup(self, request, user) method DeprecationWarning)
Это связано с тем, что в версии 0.15 метод save устарел в пользу метода def signup(request, user).
Таким образом, чтобы решить это, код примера должен быть таким:
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()
Вот что сработало для меня, объединив несколько других ответов (ни один из них не завершен на 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'
Таким образом, он использует формы модели, чтобы она была СУХОЙ, и использует новый def signup
, Я пытался положить 'myproject.myapp.forms.SignupForm'
но это привело к ошибке как-то.
@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()
В вашем 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 по множественности определения полей пользовательских моделей.
Я перепробовал много разных уроков, и все они что-то упускают, повторяют ненужный код или делают странные вещи, ниже следуют моему решению, которое объединяет все варианты, которые я нашел, оно работает, я уже запустил его в производство, НО это все еще не убедил меня, потому что я ожидал бы получить 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'
#models.py
from django.conf import settings
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
image = models.ImageField(default='users/default.png', upload_to='users')
fields = models.ForeignKey('Field' ,null=True ,on_delete=models.SET_NULL)
category = models.ForeignKey('Category' ,null=True ,on_delete=models.SET_NULL)
description = models.TextField()
interests = models.ManyToManyField('Interests')
...
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
...
def userprofile_receiver(sender, instance, created, *args, **kwargs):
if created:
userprofile = UserProfile.objects.create(user=instance)
else:
instance.userprofile.save()
post_save.connect(userprofile_receiver, sender=settings.AUTH_USER_MODEL)
#forms.py
class SignupForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(SignupForm, self).__init__(*args, **kwargs)
self.fields['first_name'].widget = forms.TextInput(attrs={'placeholder': 'Enter first name'})
self.fields['last_name'].widget = forms.TextInput(attrs={'placeholder': 'Enter last name'})
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
interests = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, help_text="Choose your interests", queryset=Interests.objects.all())
image = forms.ImageField(help_text="Upload profile image ")
fields = forms.ChoiceField(help_text="Choose your fields ")
category = forms.ChoiceField(help_text="Choose your category")
class Meta:
model = UserProfile
fields = ('first_name', 'last_name', 'name', 'image', 'fields', 'category', 'description', 'phone', 'facebook', 'twitter', 'skype', 'site', 'address', 'interests' ,'biography')
widgets = {
...
'description': forms.TextInput(attrs={'placeholder': 'Your description'}),
'address': forms.TextInput(attrs={'placeholder': 'Enter address'}),
'biography': forms.TextInput(attrs={'placeholder': 'Enter biography'}),
....
}
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.userprofile.image = self.cleaned_data.get('image')
user.userprofile.fields = self.cleaned_data['fields']
user.userprofile.category = self.cleaned_data['category']
user.userprofile.description = self.cleaned_data['description']
interests = self.cleaned_data['interests']
user.userprofile.interests.set(interests)
user.userprofile.save()
# settings.py or base.py
ACCOUNT_SIGNUP_FORM_CLASS = 'nameApp.forms.SignupForm'
Вот и все. (:
Создать модель профиля с пользователем как 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'))