如何在使用django-allauth时自定义用户配置文件

时间:2012-09-06 15:30:15

标签: django profile django-allauth

我有一个django-allauth app的django项目。我需要在注册时从用户处收集其他数据。我遇到了类似的question here,但不幸的是,没有人回答个人资料定制部分。

the documentation provided for django-allauth

  

ACCOUNT_SIGNUP_FORM_CLASS(= None

     

指向自定义表单类(例如‘myapp.forms.SignupForm’)的字符串,在注册期间用于询问用户其他输入(例如简报注册,出生日期)。该类应实现‘save’方法,接受新注册的用户作为其唯一参数。

我是django的新手并且正在努力解决这个问题。有人可以提供这种自定义表单类的示例吗?我是否还需要添加模型类以及this之类的用户对象的链接?

8 个答案:

答案 0 :(得分:153)

假设您想在注册时询问用户的姓/名。您需要将这些字段放在您自己的表单中,如下所示:

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'

就是这样。

答案 1 :(得分:22)

使用pennersr建议的解决方案,我得到了一个DeprecationWarning:

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

这是因为as of version 0.15不推荐使用save方法,而是使用def注册(请求,用户)方法。

所以要解决这个问题,示例的代码应该是这样的:

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

答案 2 :(得分:15)

这里结合了一些其他答案(其中没有一个是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',但这导致了某种错误。

答案 3 :(得分:5)

@Shreyas:以下解决方案可能不是最干净的,但它确实有效。如果您有任何建议可以进一步清理,请告诉我。

要添加不属于默认用户配置文件的信息,请先在yourapp / models.py中创建模型。阅读一般django文档以了解更多信息,但基本上:

hideHelp()

然后在yourapp / forms.py中创建一个表单:

// listen to "help" button
$('#open_help').bind("click",handleOpenHelp);

function handleOpenHelp(evt) {
    if (!$("#help").is(":visible")) {
        evt.preventDefault();
        evt.stopPropagation();

        showHelp();
    }
}



function showHelp() {
    $("#help").show();

    document.addEventListener("click",function __handler__(evt){
        evt.preventDefault();
        evt.stopPropagation();
        evt.stopImmediatePropagation();

        document.removeEventListener("click",__handler__,true);
        hideHelp();
    },true);
}



function hideHelp() {
    $("#help").hide();
}

答案 4 :(得分: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 :(得分:4)

我尝试了很多不同的教程,所有这些都缺少了一些东西,重复了不必要的代码或做了一些奇怪的事情,下面我的解决方案加入了我找到的所有选项,它正在运行,我已经把它放进去了虽然它仍然没有说服我,因为我希望在我附加到用户创建的函数中接收first_name和last_name以避免在表单中创建一个配置文件,但我不能,我想它会帮助你。 / p>

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'

答案 6 :(得分:0)

#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'

就是这样。 (:

答案 7 :(得分:-9)

使用用户作为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'))