Django-allauth का उपयोग करते समय उपयोगकर्ता प्रोफ़ाइल को कैसे अनुकूलित करें


107

मेरे पास django-allauth ऐप के साथ एक django प्रोजेक्ट है। मुझे साइनअप में उपयोगकर्ता से अतिरिक्त डेटा एकत्र करने की आवश्यकता है। मैं यहाँ एक ऐसे ही सवाल पर आया , लेकिन दुर्भाग्य से, किसी ने भी प्रोफ़ाइल अनुकूलन भाग का उत्तर नहीं दिया।

के लिए प्रदान किए गए प्रलेखन केdjango-allauth अनुसार :

ACCOUNT_SIGNUP_FORM_CLASS(= None)

कस्टम प्रपत्र वर्ग (जैसे ‘myapp.forms.SignupForm’) की ओर इशारा करते हुए एक स्ट्रिंग जो कि अतिरिक्त इनपुट के लिए उपयोगकर्ता से पूछने के लिए साइनअप के दौरान उपयोग की जाती है (जैसे न्यूज़लेटर साइनअप, जन्म तिथि)। इस वर्ग को एक ‘save’विधि को लागू करना चाहिए , नव हस्ताक्षरित उपयोगकर्ता को अपना एकमात्र पैरामीटर स्वीकार करना चाहिए ।

मैं django के लिए नया हूं और इसके साथ संघर्ष कर रहा हूं। क्या कोई ऐसे कस्टम फॉर्म क्लास का उदाहरण दे सकता है? क्या मुझे इस तरह उपयोगकर्ता ऑब्जेक्ट के लिंक के साथ एक मॉडल वर्ग जोड़ने की आवश्यकता है ?

जवाबों:


170

मान लीजिए कि आप साइनअप के दौरान उपयोगकर्ता से उसके पहले / अंतिम नाम के लिए पूछना चाहते हैं। आपको इन फ़ील्ड्स को अपने फॉर्म में रखना होगा, जैसे:

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'

बस इतना ही।


10
धन्यवाद। मूल लेखक से सुनना हमेशा अच्छा होता है :)। क्या मुझे इस जानकारी को संग्रहीत करने के लिए एक अतिरिक्त वर्ग बनाने की आवश्यकता है या क्या अलाउथ स्वचालित रूप से इसका ध्यान रखता है?
श्रेयस

12
यह वास्तव में आपके द्वारा पूछी गई जानकारी पर निर्भर करता है। किसी भी मामले में, यह सभी दायरे से परे है। यदि आप पहले / अंतिम नाम से ऊपर के उदाहरण में पूछते हैं, तो आपको एक अतिरिक्त मॉडल की आवश्यकता नहीं है और सीधे उपयोगकर्ता मॉडल में चीजों को रख सकते हैं। यदि आप उपयोगकर्ता की जन्मतिथि, उसका पसंदीदा रंग या जो कुछ भी चाहते हैं, तो आपको इसके लिए अपना स्वयं का प्रोफाइल मॉडल सेटअप करने की आवश्यकता है। कृपया ऐसा करने के तरीके पर एक नज़र डालें: docs.djangoproject.com/en/dev/topics/auth/…
pennersr

6
ठीक यही मैं चाह रहा था - पसंदीदा रंग जैसा एक अतिरिक्त क्षेत्र। यदि मुझे यह कहने में दिलचस्पी है कि पसंदीदा रंग, मेरा मानना ​​है कि मुझे एक नया UserProfile वर्ग बनाना चाहिए और फिर उपयोगकर्ता को एक से एक फ़ील्ड के रूप में और पसंदीदा रंग को अतिरिक्त फ़ील्ड के रूप में उपयोग करना चाहिए। उस स्थिति में, क्या मैं अभी भी आपके द्वारा घोषित (पसंदीदा रंग के साथ) साइनअप के एक प्रकार का उपयोग कर सकता हूं और इसके लिए ACCOUNT_SIGNUP_FORM_CLASS को हुक कर सकता हूं या क्या मुझे अपने स्वयं के कोड में डेटा बनाने और सहेजने की आवश्यकता है?
श्रेयस

4
ज़रूर, अभी भी ACCOUNT_SIGNUP_FORM_CLASS तंत्र का उपयोग किया जा सकता है। आपको बस यह सुनिश्चित करना है कि सेव () विधि को ठीक से लागू किया जाए, ताकि पसंदीदा रंग जो भी आप चाहते हैं, उसमें संग्रहीत हो।
पेन्सर

5
@pennersr - ACCOUNT_SIGNUP_FORM_CLASSकस्टम उपयोगकर्ता मॉडल फ़ील्ड को एकत्रित करने और सहेजने के लिए बहुत पहले सामाजिक साइनइन के बाद मैं इसे कैसे ऊपर नीचे कर सकता हूं ? इसके अलावा AUTH_USER_MODELgit से परिवर्तन द्वारा कस्टम उपयोगकर्ता मॉडल का उपयोग : github.com/pennersr/django-allauth को pypi में अपलोड नहीं किया गया है।
बाबू

23

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

2
@ pennsesr के उत्तर को अब उपयोग signupकरने के लिए संपादित किया गया है save
फ्लिम

18

यहाँ मेरे लिए कुछ अन्य उत्तरों को मिलाकर काम किया गया (उनमें से कोई भी 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'लेकिन किसी तरह एक त्रुटि हुई।


'myproject.myapp.forms.SignupForm' के बजाय 'yourapp.forms.SignupForm' का उपयोग करना मेरे लिए भी काम किया
alpalalpal

6

@ श्रेयस: नीचे दिया गया समाधान सबसे साफ नहीं हो सकता है, लेकिन यह काम करता है। कृपया मुझे बताएं कि क्या आपके पास इसे साफ करने के लिए कोई सुझाव है।

डिफ़ॉल्ट उपयोगकर्ता प्रोफ़ाइल से संबंधित जानकारी को जोड़ने के लिए, पहले एक मॉडल बनाएं जिसमें आप शामिल हैं। इसके बारे में और जानने के लिए सामान्य 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 / form.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()

यह ठीक वैसा ही है जैसा कि मैंने एक Django 2.0 ऐप के लिए उपयोग किया है जो वैगेट सीएमएस चला रहा है। नियमित रूप से साइन अप करने के लिए काम किया, लेकिन ऐसा लगता है कि सामाजिक प्रामाणिकता के साथ कम है?
कलोब तौलिएन

मैं Wagtail में उपयोगकर्ता के लिए व्यवस्थापक पृष्ठ पर इस अतिरिक्त फ़ील्ड को कैसे जोड़ूंगा?
यहोशू

5

आपके द्वारा 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()

सेटिंग्स में आप डाल दिया:

ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.SignupForm'

इस तरह आप बहुल उपयोगकर्ता मॉडल फ़ील्ड परिभाषा द्वारा DRY सिद्धांत को नहीं तोड़ते।


4

मैंने कई अलग-अलग ट्यूटोरियल की कोशिश की है और उनमें से सभी कुछ याद कर रहे हैं, अनावश्यक कोड को दोहराते हुए या अजीब चीजें करते हुए, bellow मेरे समाधान का अनुसरण करता है जो मुझे मिले सभी विकल्पों में शामिल होता है, यह काम कर रहा है, मैंने पहले ही इसे उत्पादन में डाल दिया है अभी भी मुझे आश्वस्त नहीं कर रहा हूं क्योंकि मैं उन कार्यों के अंदर 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'

विडंबना यह है कि यह भी कुछ चीजें याद आ रही है। प्रोफ़ाइल फ़ील्ड में कोई चूक नहीं है, और न ही वे शून्य की अनुमति देते हैं, इसलिए create_user_profileडिज़ाइन द्वारा आपका संकेत विफल हो जाता है। दूसरे, आप इसे एक सिग्नल पर कम कर सकते हैं created, विशेषकर DRY पर बात करते हुए। और तीसरा, आप अपने विचार में user.save () को कॉल करके एक प्रोफ़ाइल सहेजें को प्रभावित करते हैं, फिर वास्तविक डेटा के साथ फिर से प्रोफ़ाइल को सहेजते हैं।
मेल्विन

@Melvyn को कोष्ठक के बजाय चौकोर ब्रेसिज़ केfields = [...] साथ नहीं होना चाहिए ? fields = (...)
अहिष्टम्

यह हो सकता है, लेकिन होना नहीं है। यह केवल पढ़ने के लिए उपयोग किया जाता है केवल यह देखने के लिए कि क्या मॉडल पर फ़ील्ड प्रपत्र का हिस्सा होना चाहिए। तो यह एक सूची, टपल या सेट या किसी भी व्युत्पन्न हो सकता है। चूँकि ट्यूप्स उत्परिवर्तित नहीं होते हैं, यह ट्यूपल्स का उपयोग करने और आकस्मिक उत्परिवर्तन को रोकने के लिए अधिक समझ में आता है। प्रदर्शन के दृष्टिकोण से, ये संग्रह किसी भी प्रभाव के लिए बहुत कम व्यवहार में हैं। एक बार जब संग्रह बहुत लंबा हो जाता है, तो excludeइसके बजाय स्विच करने के लिए समझ में आ सकता है ।
मेल्विन

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'

बस इतना ही। (:


-10

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

3
धन्यवाद, लेकिन मुझे नहीं लगता कि यह वह सब है जिसकी आवश्यकता है। मेरा प्रश्न विशेष रूप से अलाउथ ऐप को संदर्भित करता है।
श्रेयस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.