Django-allauth kullanırken kullanıcı profili nasıl özelleştirilir


107

Django-allauth uygulamasıyla bir django projem var. Kayıt sırasında kullanıcıdan ek veri toplamam gerekiyor. Burada benzer bir soru ile karşılaştım ama maalesef kimse profil özelleştirme kısmına cevap vermedi.

Başına öngörülen belgeleredjango-allauth :

ACCOUNT_SIGNUP_FORM_CLASS(= None)

‘myapp.forms.SignupForm’Kullanıcıdan ek girdi (ör. Haber bülteni kaydı, doğum tarihi) istemek için kayıt sırasında kullanılan özel bir form sınıfına (örneğin ) işaret eden bir dize . Bu sınıf ‘save’, yeni kaydolan kullanıcıyı tek parametresi olarak kabul eden bir yöntem uygulamalıdır .

Django'da yeniyim ve bununla mücadele ediyorum. Birisi böyle bir özel form sınıfı örneği verebilir mi? Ben gibi kullanıcı nesnesine bir bağlantı ile de örnek bir sınıf eklemek gerekiyor mu bu ?

Yanıtlar:


170

Kayıt sırasında kullanıcıya adını / soyadını sormak istediğinizi varsayalım. Bu alanları kendi formunuza koymanız gerekecek, örneğin:

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

Ardından, ayarlarınızda şu formu işaret edin:

ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm'

Bu kadar.


10
Teşekkürler. Orijinal yazardan haber almak her zaman iyidir :). Bu bilgileri saklamak için ek bir sınıf oluşturmam gerekir mi yoksa allauth bunu otomatik olarak halleder mi?
Shreyas

12
Bu aslında sorduğunuz bilgiye bağlıdır. Her halükarda, bu tamamen kapsamı dışındadır. Yukarıdaki örnekte olduğu gibi adı / soyadını sorarsanız, fazladan bir modele ihtiyacınız olmaz ve işleri doğrudan Kullanıcı modeline yerleştirebilirsiniz. Kullanıcının doğum tarihini, en sevdiği rengi veya herhangi bir şeyi soracak olursanız, bunun için kendi profil modelinizi kurmanız gerekir. Lütfen bunun nasıl yapılacağına bir göz atın: docs.djangoproject.com/en/dev/topics/auth/…
pennersr

6
Tam olarak aradığım buydu - favori renk gibi ek bir alan. En sevdiğim renkle ilgileniyorsam, yeni bir UserProfile sınıfı oluşturup ardından Kullanıcıyı bire bir alan ve favori rengi de ek alan olarak kullanmam gerektiğine inanıyorum. Bu durumda, yukarıda beyan ettiğiniz (favori renkle) bir tür SignUpForm'u kullanmaya devam edebilir miyim ve ACCOUNT_SIGNUP_FORM_CLASS'ı buna bağlayabilir miyim yoksa formu oluşturmam ve verileri kendi kodumda kaydetmem gerekir mi?
Shreyas

4
Elbette, ACCOUNT_SIGNUP_FORM_CLASS mekanizması hala kullanılabilir. En sevdiğiniz rengin istediğiniz modelde saklanması için save () yönteminin doğru şekilde uygulandığından emin olmanız yeterlidir.
pennersr

5
@pennersr - ACCOUNT_SIGNUP_FORM_CLASSÖzel kullanıcı modeli alanlarını toplamak ve kaydetmek için ilk sosyal oturum açma işleminden sonra bunu nasıl halledebilirim ? Ayrıca AUTH_USER_MODELgit: github.com/pennersr/django-allauth adresindeki değişikliklerle özel kullanıcı modelinin kullanımı da pypi'ye yüklenmez.
Babu

23

Pennersr tarafından önerilen çözümü kullanarak bir Kullanımdan Kaldırma Uyarısı alıyordum:

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

Bunun nedeni , 0.15 sürümünden itibaren kaydetme yönteminin def kayıt (istek, kullanıcı) yöntemi lehine kullanımdan kaldırılmış olmasıdır.

Yani bunu çözmek için örneğin kodu şu şekilde olmalıdır:

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
@ pennsesr'in yanıtı artık signupyerine kullanılmak üzere düzenlendi save.
Flimm

18

İşte diğer birkaç cevabı birleştirerek benim için işe yarayan şey (hiçbiri% 100 tam ve KURU değil).

İçinde 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()

Ve içinde settings.py:

ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.SignupForm'

Bu şekilde model formlarını kullanır, böylece KURU olur ve yenisini kullanır def signup. Koymayı denedim 'myproject.myapp.forms.SignupForm'ama bu bir şekilde bir hatayla sonuçlandı.


'myproject.myapp.forms.SignupForm' yerine 'yourapp.forms.SignupForm' kullanmak benim için de işe yaradı
alpalalpal

6

@Shreyas: Aşağıdaki çözüm en temiz olmayabilir, ancak işe yarıyor. Daha fazla temizlemek için herhangi bir öneriniz varsa lütfen bize bildirin.

Varsayılan kullanıcı profiline ait olmayan bilgileri eklemek için, önce yourapp / models.py içinde bir model oluşturun. Hakkında daha fazla bilgi edinmek için genel django belgelerini okuyun, ancak temel olarak:

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)

Ardından, uygulamanız / forms.py'de bir form oluşturun:

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

Wagtail CMS'yi çalıştıran bir Django 2.0 uygulaması için kullandığım şey tam olarak buydu. Normal kayıt için çalıştı, ancak Sosyal Yetkili ile daha az mı görünüyor?
Kalob Taulien

Wagtail'deki kullanıcı için bu ekstra alanı yönetici sayfasına nasıl eklerim?
Joshua

5

Gözlerinde farklı users/forms.pysen koyun:

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 içinde şunu koyarsınız:

ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.SignupForm'

Bu şekilde, KURU prensibini çokluk Kullanıcı modelleri alan tanımıyla bozmazsınız.


4

Birçok farklı öğretici denedim ve hepsinde bir şeyler eksik, gereksiz kodlar tekrarlanıyor veya tuhaf şeyler yapıyor, aşağıda bulduğum tüm seçenekleri birleştiren çözümümü takip ediyor, çalışıyor, zaten üretime koydum AMA onu hala beni ikna etmiyor çünkü Kullanıcılara eklediğim işlevlerin içinde ilk_adı ve soyadı form içinde bir profil oluşturmaktan kaçınmak için oluşturmayı bekliyordum ama yapamadım, dışarıdan size yardımcı olacağını düşünüyorum.

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'

İronik olarak, bunda da birkaç şey eksik. Profil alanlarının varsayılanları yoktur ve boş değerlere izin vermezler, bu nedenle create_user_profilesinyaliniz tasarım gereği başarısız olur. İkinci olarak, bunu createdözellikle KURU konuşmaya bağlı olarak tek bir sinyale indirgeyebilirsiniz . Üçüncüsü, görünümünüzde user.save () 'yi arayarak ve ardından profili gerçek verilerle yeniden kaydederek bir Profil kaydetme gerçekleştirirsiniz.
Melvyn

@Melvyn Should olmasın fields = [...]ile kare parantezler yerine fields = (...) parantez?
Ahtisham

Olabilir ama olmak zorunda değil. Yalnızca Model üzerindeki alanın formun bir parçası olması gerekip gerekmediğini kontrol etmek için salt okunur kullanılır. Dolayısıyla bir liste, demet veya küme veya bunların herhangi bir türevi olabilir. Tuplelar değişken olmadığından, tuple kullanmak ve tesadüfi mutasyonları önlemek daha mantıklıdır. Performans açısından bakıldığında, bu koleksiyonlar pratikte herhangi bir etki yaratamayacak kadar küçüktür. Koleksiyon çok uzun sürdüğünde, bunun excludeyerine geçiş yapmak mantıklı olabilir .
Melvyn

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'

İşte bu. (:


-10

OneToOneField olarak kullanıcıyla bir Profil Modeli oluşturun

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

3
Teşekkürler, ama tek ihtiyacın bu olduğunu sanmıyorum. Sorum özellikle allauth uygulamasıyla ilgili.
Shreyas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.