1

I´m trying to update the data of an existing model with a csv. I read the file and assign the values with no problem.

If I try `MyModel.update() everything runs with no error but the data is not saved.

with open('Productosold.csv') as csvfile:
     reader = csv.DictReader(csvfile)
     for row in reader:
        p = ProductosBase.objects.filter(codigo_barra = row['codigo_barra'])
        p.region=row['region']
        p.producto_ing=row['producto_ing']
        p.packaging_ing=row['packaging_ing']
        p.precio_compra=row['precio_compra']
        p.uom=row['uom']
        p.units_inner=row['units_inner']
        p.inner_master=row['inner_master']
        p.tier=row['tier']
        p.precio_lista_internacional=row['precio_lista_internacional']
        p.update()

I usualy upload new data using the MyModel.save() method and have no problem. Now, if I use that I get "Queryset has no attribute save".

p.save()

If I print some of the p.values I can see they are populated correctly from the csv file.

What I´m doing wrong?

Thanks in advance!

Francisco Ghelfi
  • 872
  • 1
  • 11
  • 34

2 Answers2

0

.filter always returns a queryset, not a single instance. When you set all those values, you are just setting (previously non-existing) attributes onto that queryset object; you are not setting fields in a model instance. You should use .get to get an instance and save that.

p = ProductosBase.objects.get(codigo_barra = row['codigo_barra'])
p.region=row['region']
...
p.save()

However, since all the columns in your CSV map precisely to fields on the model, you could in fact use filter and update to do the whole thing in one go:

for row in reader:
    ProductosBase.objects.filter(codigo_barra=row['codigo_barra']).update(**row)

and no need for any of the rest of the code.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
-1

You need filter() whenever you expect more than just one object that matches your criteria. If no item was found matching your criteria, filter() returns am empty queryset without throwing an error.

Also you can use get() but when you expect one (and only one) item that matches your criteria. Get throws an error if the item does not exist or if multiple items exist that match your criteria. You should therefore always use if in a try.. except .. block or with a shortcut function like get_object_or_404 in order to handle the exceptions properly. I'd recommend using get_object_or_404 in this case.

p = get_object_or_404(ProductosBase, codigo_barra=row['codigo_barra'])
Shaig Khaligli
  • 4,955
  • 5
  • 22
  • 32
  • The question clearly states the code is being run from the shell. It makes no sense to raise a 404 in the shell. – Daniel Roseman Mar 18 '19 at 22:20
  • @DanielRoseman thanks for noting that ! But that doesn't make sense. It's for in order to handle exceptions properly. – Shaig Khaligli Mar 18 '19 at 22:23
  • 1
    What? `get_object_or_404` *raises* an exception. But it's an exception that only applies in a web request, causing the server to return a 404 error code. It's of no use in a try/except block; `.get()` will already raise the more appropriate exception, which is ModelDoesNotExist. – Daniel Roseman Mar 18 '19 at 22:27
  • @DanielRoseman Thanks for information. Yes you're right. If this will be run in web request, it's better to use `get_object_or_404`. But if it's in shell, your variant would be better. – Shaig Khaligli Mar 18 '19 at 22:31