xnx
xnx

Reputation: 25548

Saving Profile model after update: IntegrityError (duplicate user_id key)

My Django site has two sorts of user profiles, one for regular users (MyUserProfile) and one, which extends it, for employees (EmployeeUserProfile). models.py:

class MyUserProfile(models.Model):
    user = models.OneToOneField('auth.user', related_name='userprofile')
    www = models.URLField(null=True, blank=True, verbose_name='website')
    affiliation = models.CharField(max_length=200,null=True,blank=True)
    ...

class EmployeeUserProfile(MyUserProfile):
    start_date = models.DateField()
    current = models.BooleanField(default=True)
    ...

I have a problem implementing an profile update form for employees. I create the form thus (forms.py):

from django.forms import ModelForm
from .models import EmployeeUserProfile

class EmployeeUserProfileForm(ModelForm):
    class Meta:
        model = EmployeeUserProfile
        exclude = ['user', 'current']

But when I come to updating the profile:

from django.template import RequestContext
from .forms import EmployeeUserProfileForm

def update_profile(request):
    if request.method == 'POST':
        form = EmployeeUserProfileForm(request.POST)
        if form.is_valid():
            profile = form.save(commit=False)
            profile.user = request.user
            profile.save()
    else:
        user = request.user
        profile = user.userprofile.employeeuserprofile
        form = EmployeeUserProfileForm(instance=profile)
    c = {'form': form}
    return render_to_response('pages/profile/update.html', c,
                              context_instance=RequestContext(request))

On 'submit' for updating an already-created profile I get an IntegrityError. For example, (1062, "Duplicate entry '2' for key 'user_id'"). Apparently Django is trying to add a copy of the user instead of updating the existing one.

What am I doing wrong?

Upvotes: 1

Views: 974

Answers (1)

karthikr
karthikr

Reputation: 99660

You need to pass the instance argument in the POST condition too

form = EmployeeUserProfileForm(request.POST)

should be

form = EmployeeUserProfileForm(request.POST, instance=profile)

By not sending the instance argument, form tries to create instead of update. Note that this would mean you would have to move the else block above if

Something like this:

@login_required
def update_profile(request):

    user = request.user
    profile = user.userprofile.employeeuserprofile
    form = EmployeeUserProfileForm(instance=profile)

   if request.method == 'POST':
        form = EmployeeUserProfileForm(request.POST, instance=profile)
        if form.is_valid():
            profile = form.save(commit=False)
            profile.user = request.user
            profile.save()

    c = {'form': form}
    return render_to_response('pages/profile/update.html', c,
                              context_instance=RequestContext(request))

You might also want to use the login_required decorator so that you dont run into issues with anonymous user, etc..

Upvotes: 5

Related Questions