Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django error <model> object has no attribute 'update'

UPDATE

I was doing some maintenance on the server and rebooted... once it came back the code worked just fine... which actually makes me to worry just the same...

i think it's a bug on mod_wsgi.

Thanks anyway!

I'm really new to django (started yesterday). I managed to make a excel parser using xlrd, everything works fine with the data (it loads really really fast), i need to update the file info in the database so i can know how the load is going, this is where i have the problem, the save() method doesn't work, I already used update along with get and filter, but always the same problem.

I hope you can point me out where is the mistake

models.py

class archivo(models.Model):
    archivo_id = models.AutoField(primary_key=True)
    fk_cliente = models.IntegerField()
    fk_usuario = models.IntegerField()
    archivo_nombre = models.CharField(max_length = 30)
    archivo_original = models.CharField(max_length = 255)
    archivo_extension = models.CharField(max_length = 5)
    archivo_tamano = models.FloatField()
    archivo_registros = models.IntegerField()
    archivo_registros_buenos = models.IntegerField()
    archivo_registros_malos = models.IntegerField()
    archivo_registros_cargados = models.IntegerField()
    archivo_fecha_carga = models.DateTimeField()
    archivo_fecha_envio = models.DateTimeField()
    def __unicode__(self):
        return self.archivo_id

views.py

from procesa.models import *
from django.conf import settings
from django.shortcuts import render_to_response  
import xlrd
from time import strftime
from symbol import except_clause
def procesa(request, procesar = 0):
    datos = None
    infoarchivo = None
    if(procesar > 0):
        try:
            infoarchivo = archivo.objects.get(archivo_id=int(procesar))
        except:
            return render_to_response('error.html')

    if (infoarchivo is not None):
        excel_path = settings.FILES_URL+infoarchivo.archivo_original
        wb = xlrd.open_workbook(str(excel_path))
        sh = wb.sheet_by_index(0)
        ##START UPDATE##
        infoarchivo2 = archivo.objects.filter(archivo_id = procesar)
        infoarchivo2.archivo_registros = sh.nrows
        infoarchivo2.save()
        ##END UPDATE##            
        for rownum in range(sh.nrows):
            destino = str(sh.cell(rownum,0).value)
            destino = destino.replace(".0","")
            if (int(destino) > 0):
                mensaje = str(sh.cell(rownum,1).value)
                ahora = strftime("%Y-%m-%d %H:%M:%S")
                reg = registro.objects.filter(registro_destino__exact=destino,fk_archivo__exact=procesar)
                #reg = registro.objects.raw(str(el_query))

                if (reg.exists()):
                    exists = True
                else:
                    r = registro(fk_cliente=1,fk_usuario=1,fk_archivo=int(procesar),registro_destino=destino,registro_mensaje=mensaje,registro_estado='Cargado',registro_fecha_carga=ahora)
                    r.save()


        datos = {'ID':procesar,'PATH': settings.FILES_URL, 'INFO':infoarchivo, 'el_excel':infoarchivo.archivo_original, 'registros':sh.nrows }
        return render_to_response('carga.html', {'datos': datos})

in the ##START UPDATE## block i've already tried with

infoarchivo.archivo_registros = sh.nrows
infoarchivo.save()

and

archivo.objects.filter(archivo_id = procesar).update(archivo_registros=sh.nrows)

and

archivo.objects.get(archivo_id = procesar).update(archivo_registros=sh.nrows)

I can't find any reference to this error or something else to add in the models file, i'm pretty sure it's something really easy to fix, but i just can't find it.

The error i'm getting (for all the different codes) is

Exception Type: AttributeError at /procesa/4

Exception Value: 'archivo' object has no attribute 'update'

The records of the file gets parsed and inserted with no problem.

I'm using Django 1.5 with python 2.7 in Apache 2.2 with mod_wsgi and mysql backend installed in EC2 on Amazon

UPDATE I was doing some maintenance on the server and rebooted... once it came back the code worked just fine... which actually makes me to worry just the same...

i think it's a bug on mod_wsgi.

Thanks anyway!

like image 649
mariofix Avatar asked Mar 08 '13 22:03

mariofix


3 Answers

The reason for this error is that .get() returns an individual object and .update() only works on querysets, such as what would be returned with .filter() instead of .get().

If you are using .get(), then .update() will not work. You will need to save the information to the object manually:

archivo = archivo.objects.get(archivo_id=procesar)
archivo.archivo_registros = sh.nrows
archivo.save()

You can also use update_fields if you only wish to save this particular piece of data:

archivo = archivo.objects.get(archivo_id=procesar)
archivo.archivo_registros = sh.nrows
archivo.save(update_fields=['archivo_registros'])

This prevents triggering any signals that you may not want to invoke.

Your other option is to simply use .filter().

archivo = archivo.objects.filter(archivo_id=procesar).update(archivo_registros=sh.nrows)

Note that this will update multiple objects if they exist. If you want to be sure that doesn't happen, you should include the primary key in the filter, or use one of the earlier approaches to make sure you are only modifying a single object.

like image 163
Adam Starrh Avatar answered Nov 09 '22 14:11

Adam Starrh


Encountered this behavior and used a "filter" then update works as expected. For example:

 Students.objects.select_for_update().filter(id=3).update(score = 10)

Just FYI: Unless you are handling transactions, modifying each field separately using save() might create data inconsistency in a multi-threaded environment. By the time threadA calls save() on a model, another threadB could have changed the model fields and saved. In which case threadA has to read the updated model and change.

This was on Django 1.6.2

like image 11
quiet_penguin Avatar answered Nov 09 '22 13:11

quiet_penguin


I have had similar case, but it worked when using construction like:

this_spot = Spot.objects.filter(pk=obj.spot.pk)
this_spot.update(friendly_rate=rating_to_be_persisted)

but not working in case, where I wanted access directly single instance, e.g from foreign key side class. Returning 'Spot' object has no attribute 'update'.

The reason is simply the way update() works described in django documentation:

The way around is approach like shown on the django site:

>>> b = Blog.objects.get(pk=1)

# Update all the headlines belonging to this Blog.
>>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')
like image 3
andilabs Avatar answered Nov 09 '22 13:11

andilabs