A better way of checking if a record exists

2,001 views
Skip to first unread message

ALJ

unread,
Oct 1, 2010, 4:21:01 AM10/1/10
to Django users
I'm running through a spreadsheet to update customer info. It takes
quite a while and I was just trying to optimize things a bit. I want
to check if the record is already there and if so update it with the
newer data. If not append it to the table.

Two code snippets below ...

<code>
try:
customer = models.Retailer.objects.get(shared_id='1')
except models.Retailer.DoesNotExist:
customer = models.Retailer()
</code>

This just seems 'dirty' to me. I mean, using the exceptions this way.
Exceptions to me feel as if they are the last resort when things go
wrong. But on the other hand it is probably quicker than ...

<code>
if models.Retailer.objects.filter(shared_id='1'):
customer = models.Retailer.objects.get(shared_id='1')
else:
customer = models.Retailer()
</code>

This seems cleaner but doubles the calls to the database.

Is the first really the 'accepted' way of doing this?

ALJ

Shawn Milochik

unread,
Oct 1, 2010, 4:29:30 AM10/1/10
to django...@googlegroups.com
For what it's worth, I use the get_or_create with the 'default' keyword to do this:

for record in reader:

new_values = {
'product_code': slugify(record['Product Code']),
'msrp': record['Suggested Retail'],
#etc...
}

product, was_created = Product.objects.get_or_create(source_id = record['Source ID'], defaults = new_values)

if not was_created:
product.product_code = slugify(record['Product Code'])
product.msrp = record['Suggested Retail']
#etc...
product.save()

I don't like the DRY violation, but a model instance doesn't have an update() method like a queryset for me to dump the kwargs into -- unless I'm missing something.

Shawn


bruno desthuilliers

unread,
Oct 1, 2010, 5:57:02 AM10/1/10
to Django users


On 1 oct, 10:29, Shawn Milochik <sh...@milochik.com> wrote:
> For what it's worth, I use the get_or_create with the 'default' keyword to do this:
>
> for record in reader:
>
>     new_values = {
>         'product_code': slugify(record['Product Code']),
>         'msrp': record['Suggested Retail'],
>         #etc...
>     }
>
>     product, was_created = Product.objects.get_or_create(source_id = record['Source ID'], defaults = new_values)
>
>     if not was_created:
>         product.product_code = slugify(record['Product Code'])
>         product.msrp = record['Suggested Retail']
>         #etc...

Err... What about:

if not was_created:
for attrname, value in new_values.items():
setattr(product, attrname, value)
product.save()


> I don't like the DRY violation, but a model instance doesn't have an update() method like a queryset for me to dump the kwargs into -- unless I'm missing something.

For "direct" model fields you could use the infamous
obj.__dict.__.update() hack but it's dirty and brittle - and it still
won't work with foreign keys, m2ms etc.

Now nothing prevents you from providing this model.update method...

ALJ

unread,
Oct 1, 2010, 6:34:20 AM10/1/10
to Django users
... what is the infamous obj.__dict__.update() hack?

On Oct 1, 11:57 am, bruno desthuilliers

Thomas Guettler

unread,
Oct 1, 2010, 7:24:11 AM10/1/10
to django...@googlegroups.com
Hi,

I really would love the see this dictionary like access:

obj=MyModel.objects.get(primary_key)
if obj is None:
... does not exist.

But the ticket was closed:

http://code.djangoproject.com/ticket/5741

Thomas

--
Thomas Guettler, http://www.thomas-guettler.de/
E-Mail: guettli (*) thomas-guettler + de

bruno desthuilliers

unread,
Oct 1, 2010, 7:45:09 AM10/1/10
to Django users

ShawnMilo

unread,
Oct 2, 2010, 3:18:27 PM10/2/10
to Django users
Bruno,

Great point. I've simplified my old code quite a bit with this
suggestion.

After creating a dictionary with 12 items in it, I use it for the
default in get_or_create, then:

[setattr(product, field, value) for field, value in
new_values.items()]
product.save()

Thanks,
Shawn
Reply all
Reply to author
Forward
0 new messages