just__matt
just__matt

Reputation: 484

Django: Form.save() INSERT will not work, only UPDATE

ok, so I go to the view for 'employment_add', I enter values in the fields of a Django form, then submit.

Success, It creates a new employment record and the page reloads with an empty form.

When I enter values and submit the second time, it updates; even though I am not passing an instance to the form and it is unbound.

I would like it to create a new employment record instead.

Any suggestions? Thanks for your help.

---UPDATE---

Following on from Rajiv's answer: I don't understand where Django is getting the uuid of the previous object from. can anyone explain where in the RequestContext this information is being stored? There is no uuid(pk) field in the form or POST data, and I can't find it anywhere in the RequestContext. I am not passing an instance to the Form in either scenario... any explanation would be much appreciated

---UPDATE--- The issue appears to be at the instanciation of Employment, in the employment_add view. Please see the pdb trace below the code

===MODELS===

###User Model is provided by Django

import uuid
def make_uuid():
    return str(uuid.uuid4())

class __base__(models.Model):
    uuid = models.CharField(max_length=36, primary_key=True,
      default=make_uuid(), editable=False)
        #max_length must be 36. uuid4 generates a 36 character key

    class Meta:
        abstract = True

class Employment(__base__):
    user = models.ForeignKey( User, related_name='employment')
    ### employment related fields - no other PK or FK

===FORM===
class EmploymentForm(ModelForm):
class Meta:
    model = Employment
    exclude = ('user')
    widgets = {
    }

===VIEW===
def employment_add(request):
    context_instance = RequestContext(request)
    u = request.user
    if request.method == 'POST':
        message=""
        form = EmploymentForm(request.POST)
        if form.is_valid():
            f = form.save(commit=False)
            f.user = u
            f.save()
            message = "Position Added"
            form = EmploymentForm()
        return render_to_response("employment_add.html", {'form':form,    'message':message}, context_instance)
    else:
        em = Employment()
        #start pdb trace here
        form = EmploymentForm(instance=em)
    return render_to_response("employment_add.html", {'form': form},   context_instance)

===pdb trace===

(Pdb) em
<Employment: Employment object>
(Pdb) em.uuid
u'260015bc-c2eb-4cc1-9506-75e312027404'  
(Pdb) c

[29/Aug/2011 14:15:25] "GET /person/employment/add HTTP/1.1" 200 4425

[29/Aug/2011 14:15:33] "POST /person/employment/add HTTP/1.1" 302 0
<QueryDict: {u'month_start': [u''], u'year_start': [u''], u'year_end': [u''], u'employer': [u'66'], u'details': [u'6'], u'month_end': [u''], u'position': [u'66'], u'csrfmiddlewaretoken': [u'9e9c6b2ac43c370f993cb3f72682c7ea'], u'city_town': [u'']}>

[29/Aug/2011 14:15:33] "GET /person/view?i=1 HTTP/1.1" 200 9255
(Pdb) em
<Employment: Employment object>
(Pdb) em.uuid
u'260015bc-c2eb-4cc1-9506-75e312027404'
(Pdb) 

Upvotes: 0

Views: 572

Answers (2)

rczajka
rczajka

Reputation: 1840

The problem seems to be the default=make_uuid(). This runs make_uuid only once, on model class creation, and passes the one generated value (not the function) as the default value for the field. Every time you create an instance, the same default value is used.

You should pass a callable as the default instead, as in: default=make_uuid.

Upvotes: 3

Rajiv Makhijani
Rajiv Makhijani

Reputation: 3651

In the end of your code:

else:
    form = EmploymentForm()
return render_to_response("employment_add.html", {'form': form},   context_instance)

remove the context_instance from the call to render_to_response. This context instance contains the submitted form data and is pre-populating the form the second time.

Upvotes: 0

Related Questions