views:

339

answers:

4

Hi I am using Django ModelForms to create a form. I have my form set up and it is working ok.

form = MyForm(data=request.POST)

if form.is_valid():
    form.save()

What I now want though is for the form to check first to see if an identical record exists. If it does I want it to get the id of that object and if not I want it to insert it into the database and then give me the id of that object. Is this possible using something like:

form.get_or_create(data=request.POST)

I know I could do

form = MyForm(instance=object)

when creating the form but this would not work as I still want to have the case where there is no instance of an object

edit:

Say my model is

class Book(models.Model):
    name = models.CharField(max_length=50)
    author = models.CharField(max_length=50)
    price = models.CharField(max_length=50)

I want a form which someone can fill in to store books. However if there is already a book in the db which has the same name, author and price I obviously don't want this record adding again so just want to find out its id and not add it.

I know there is a function in Django; get_or_create which does this but is there something similar for forms? or would I have to do something like

if form.is_valid(): 
    f = form.save(commit=false)
    id = get_or_create(name=f.name, author=f.author, price=f.price)

Thanks

+1  A: 

You just need two cases in the view before the postback has occurred, something like

if id:
    form = MyForm(instance=obj)
else
    form = MyForm()

then you can call form.save() in the postback and Django will take care of the rest.

Tom
With the assumption that after the "if id" you instantiate the obj variable properly.
Tom
see edit above for more info. Thanks
John
A: 

What do you mean by "if an identical record exists"? If this is a simple ID check, then your view code would look something like this:

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
        form.save()
else:
    if get_id:
        obj = MyModel.objects.get(id=get_id)
        form = MyForm(instance=obj)
    else:
        form = MyForm()

The concept here is the check occurs on the GET request, such that on the POST to save, Django will already have determined if this is a new or existing record.

If your check for an identical record is more complex, it might require shifting the logic around a bit.

Marc L
see edit above for more comments. Thanks
John
+1  A: 

I like this approach:

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
       book, created = Book.objects.get_or_create(**form.cleaned_data)

That way you get to take advantage of all the functionality of model forms (except .save()) and the get_or_create shortcut.

rz
A: 

I would do this -

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
        name   = form.cleaned_data['name']
        author = form.cleaned_data['author']
        price  = form.cleaned_data['prince']

        if name and author and price:
            book, created = Book.objects.get_or_create(name=name, \
              author=author, price=price)

            if created:
                # fresh entry in db.
            else:
                # already there, maybe update?

            book.save()
MovieYoda