Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow changing of User fields (like email) with django-profiles

Django lets you create a model foreign-keyed to User and define it in settings as the official "profile" model holding additional data for user accounts. django-profiles lets you easily display/create/edit that profile data. But the user's primary email address is part of their main account, not part of their extended profile. Therefore when you put

{{ form }}

in the profile/edit_profile template, the primary email address does not show up. You can retrieve it manually with

{{ user.email }}

but changes to it aren't saved back to the account upon submit of course. I'm assuming a custom ModelForm has been created, such as:

class ProfileForm(ModelForm):

  class Meta:
      model = Parent
      exclude = ('family','user','board_pos','comm_job',)

and that ProfileForm is being passed to django-profiles' view code with a urlconf like:

('^profiles/edit', 'profiles.views.edit_profile', {'form_class': ProfileForm,}),

The same problem would come up if you wanted to let users change their first or last names. What's the best way to let users change their own email addresses or names when using django-profiles?

like image 385
shacker Avatar asked Dec 22 '22 10:12

shacker


1 Answers

Here's the solution we ended up using:

# urls.py
    # First match /profiles/edit before django-profiles gets it so we can pass in our custom form object.
    ('^profiles/edit', 'profiles.views.edit_profile', {'form_class': ProfileForm,}),
    (r'^profiles/', include('profiles.urls')),

Now we override the save method in the form itself, so that when the form is saved, the email address is pushed into the saving user's User object at the same time. Graceful.

# forms.py , trimmed for brevity

class ProfileForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(ProfileForm, self).__init__(*args, **kwargs)
        try:
            self.fields['email'].initial = self.instance.user.email
        except User.DoesNotExist:
            pass

    email = forms.EmailField(label="Primary email")

    class Meta:
      model = Parent

    def save(self, *args, **kwargs):
      """
      Update the primary email address on the related User object as well. 
      """
      u = self.instance.user
      u.email = self.cleaned_data['email']
      u.save()
      profile = super(ProfileForm, self).save(*args,**kwargs)
      return profile

Works perfectly. Thanks mandric.

like image 166
shacker Avatar answered Dec 28 '22 06:12

shacker