DzLL February 2016

ModelForm right approach for editing database record?

Can someone help me with fixing Django ModelForm?

This particular code can add new item to database as expected, but when I'm trying to edit db record - It just add new record, instead of updating old. I'm quite new in Django framework.

views.py:

def manage(request, item_id = None):
    t = get_object_or_404(Hardware, id=item_id) if item_id else None
    form = Manage(request.POST or None, instance=t)

if t:
    if form.is_valid():
        #form.save()
        hostname = form.cleaned_data['hostname']
        cpu = form.cleaned_data['cpu']
        os = form.cleaned_data['os']
        ram = form.cleaned_data['ram_total']
        storage = form.cleaned_data['storage']
        hostdata = Hardware(
        hostname=hostname,
        cpu=cpu,
        ram_total=ram,
        os=os,
        storage=storage,
        lock_state=t.lock_state, # because in edit operation we shouldn't change it.
        lock_date=t.lock_date, # because in edit operation we shouldn't change it.
        locked_by=t.locked_by) # because in edit operation we shouldn't change it.
        hostdata.save()
        return HttpResponseRedirect(reverse('main:index'))
elif not t:
    if form.is_valid():
        hostname = form.cleaned_data['hostname']
        cpu = form.cleaned_data['cpu']
        os = form.cleaned_data['os']
        ram = form.cleaned_data['ram_total']
        storage = form.cleaned_data['storage']
        current_user = request.user
        user = User.objects.get(id=current_user.id)
        hostdata = Hardware(
        hostname=hostname,
        cpu=cpu,
        ram_total=ram,
        os=os,
        storage=storage,
        lock_state=0,
        lock_date=datetime.datetime.now(),
        locked_by=user)
        hostdata.save()
        return HttpResponseRedirect(reverse('main:index'))

return render(request, 'hardware/edit.html', {'form': form})

models.py:

class Hardware(models.Model):
        

Answers


Aviah Laor February 2016

Try Class Based View, which in it's simplest looks like:

from django.views import generic
class HardwareEditView(generic.UpdateView):

    template_name = "hardware.html"
    form_class = Manage

You will have to add get_absolute_url to the model. Generic class based views are exactly for this standard create/update/view common tasks.


Derek Kwok February 2016

You already retrieved the instance t in the first line of your view. The code below will always create a new instance (unless you specify the pk parameter):

 hostdata = Hardware(...)
 hostdata.save()

Simply do this instead:

 if t:
     if form.is_valid():
         t.hostname = form.cleaned_data['hostname']
         t.cpu = form.cleaned_data['cpu']
         ....
         t.save()

However, you really should rely on the save method provided by the ModelForm as the other answers suggested. Here's an example:

 def manage(request, item_id=None):
     t = get_object_or_404(Hardware, id=item_id) if item_id else None

     # if t is None, a new object will be created in form.save()
     # if t is an instance of Hardware, t will be updated in form.save()
     form = Manage(request.POST, instance=t)

     if form.is_valid():
         form.save()
         return HttpResponseRedirect(reverse('main:index')

     return render(request, 'hardware/edit.html', {'form': form})

You also specified fields in your form:

fields = ['hostname', 'os', 'cpu', 'ram_total', 'storage']

These are the fields which will be set or updated when you call form.save().


doru February 2016

I think something like this - using update_fields - should work:

def manage(request, item_id = None):
    t = get_object_or_404(Hardware, id=item_id)
    form = Manage(request.POST or None, instance=t)

if t:
    if form.is_valid():
        #form.save()
        t.hostname = form.cleaned_data['hostname']
        t.cpu = form.cleaned_data['cpu']
        t.os = form.cleaned_data['os']
        t.ram = form.cleaned_data['ram_total']
        t.storage = form.cleaned_data['storage']   
        t.save(update_fields=['hostname', 'cpu', 'os','ram','storage'])
        return HttpResponseRedirect(reverse('main:index')) 
........

Post Status

Asked in February 2016
Viewed 3,109 times
Voted 11
Answered 3 times

Search




Leave an answer