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!
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.
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
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')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With