Search code examples
pythondjangodjango-allauth

extend a user profile in django to include profile photo


I am trying to extend a user profile in django so that user can add profile photo and birthday date and I am using django-allauth for my user authentication. I am currently following a reference but for the reference a new user registration was used without involving django-allauth. I have thus implemented the codes but stock on one point where I can not figure out where to place this particular line of code

# Create the user profile
profile = Profile.objects.create(user=new_user)

below is the profile Edit code Model

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL)
    date_of_birth = models.DateField(blank=True, null=True)
    photo = models.ImageField(
            upload_to= upload_location,
            null = True,
            blank = True,
            height_field = "height_field",
            width_field = "width_field")

    def __str__(self):
        return 'Profile for user {}'.format(self.user.username)

Form.py

class UserEditForm(forms.ModelForm):
    username = forms.CharField(required=True)
    email = forms.EmailField(required=True)
    first_name = forms.CharField(required=False)
    last_name = forms.CharField(required=False)

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email']

class ProfileEditForm(forms.ModelForm):
    """docstring for ProfileEditForm."""
    class Meta:
        model = Profile
        fields = ['date_of_birth', 'photo']

View

def edit(request):
    if request.method == 'POST':
        user_form = UserEditForm(instance = request.user, data = request.POST)
        profile_form = ProfileEditForm(instance = request.user.profile, data = request.POST, files = request.FILES)

        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()

    else:
        user_form = UserEditForm(instance= request.user)
        profile_form = ProfileEditForm(instance=request.user.profile)

   return render(request, 'account/edit.html',
    {'user_form': user_form, 'profile_form': profile_form})

and if I try to run the code like that I get an error User has no profile. any further code would be presented based on request.

Urls

url(r'^profile/edit/$', views.edit, name='update_profile'),

Template

<form method="POST" action="." class="" enctype="multipart/form-data"/>
    {% csrf_token %}
    {{ user_form.as_p }}
    {{ profile_form.as_p }}
    <input type="submit" name="submit" value="update">

</form>

Solution

  • In your view, add (or add elsewhere, and import):

    def load_profile(user):
      try:
        return user.profile
      except:  # this is not great, but trying to keep it simple
        profile = Profile.objects.create(user=user)
        return profile
    

    Then change your view function to use load_profile(request.user) instead of request.user.profile.

    View

    def edit(request):
        profile = load_profile(request.user)
        if request.method == 'POST':
            user_form = UserEditForm(
                instance=request.user,
                data=request.POST,
            )
            profile_form = ProfileEditForm(
                instance=profile,
                data=request.POST,
                files=request.FILES,
            )
    
            if user_form.is_valid() and profile_form.is_valid():
                user_form.save()
                profile_form.save()
    
        else:
            user_form = UserEditForm(instance=request.user)
            profile_form = ProfileEditForm(instance=profile)
    
        return render(
            request,
            'account/edit.html',
            {'user_form': user_form, 'profile_form': profile_form}
        )