Your problem lies on the way Django actually carries out create or update.
As name suggest, create or update does either one. But that's what you
don't want - you want conditional update.
Only update if certain fields have been changed. Well this can be done
few ways.
So you want to do
"update_only_if_at_least_one_of_default_fields_changed_or_create"
Operation is simple, if object is not found, create new one using
defaults if found, pull values as a dict, compare against
default values and if at least one differs do an update. Otherwise don't
do anything.
So basically code would look something like this:
update_if_changed_or_create(**kwargs):
defaults = kwargs.pop('defaults', None)
qs = MyModel.objects.filter(**kwargs)
if not qs:
obj = MyModel(**kwargs).save()
return obj, True # Created object
else if len(qs) == 1:
obj = qs[0]
changed = False
for k, v in defaults:
if getattr(obj, k) != v:
changed = True
setattr(obj, k, v)
if changed:
obj.save()
return obj, False # Updated object
else:
# Multiple objects...
return obj, None # No change.
On 06.11.2015 14:08, Yunti wrote:
Carsten ,
Thanks for your reply,
A note about the last statement: If a Supplier object has the same
unique_id, and all
other fields (in `defaults`) are the same as well, logically there is
no difference
between updating and not updating – the result is the same.
The entry in the database is the same - apart from the last_updated
flag if it's not rewritten over the top of it. This means I can check
for new data often and be alerted when there is an actual update (i.e.
a change to the data). If it rewrites the data everytime it checks
then I have no idea when data was actually updated.
Have you checked? How?
In your create_or_update_if_diff() you seem to try to re-invent
update_or_create(), but
have you actually examined the results of the
supplier, created = Supplier.objects.update_or_create(...)
call?
I checked by seeing that the last_updated field in the database was
updated everytime. (I suppose the issue could be with how that field
gets reset to the next time it's run- I didn't eliminate that
possibility.)
Yes I was worried that I might be recreating (a poor version) of
update_or_create() but it didn't seem to have the option where it
wouldn't write to the database if there was no change to the data.
Can it do this? And how would I verify when an item has been updated
or created (or neither) - could I output to the console?
If it can how do I call it so it checks against all fields (unique_id
and defaults) and updates using the defaults if it finds a difference
(and creates if it doesn't find a unique_id)?
I'm still not sure if this is possible and how to call the function,
particular how to pass in the remaining defaults to check against -
**kwargs = defaults isn't right but not sure what it should be.
supplier, created =
Supplier.objects.update_or_create(unique_id=product_detail['supplierId'],
**kwargs=defaults, defaults={ 'name': product_detail['supplierName'],
'entity_name_1': entity_name_1, 'entity_name_2': entity_name_1,
'rating': product_detail['supplierRating']})
On Thursday, 5 November 2015 20:05:39 UTC, Carsten Fuchs wrote:
Hi Yunti, Am 05.11.2015 um 18:19 schrieb Yunti: > I have tried to
use the update_or_create() method assuming that it would either,
create > a new entry in the db if it found none or update an
existing one if it found one and had > differences to the defaults
passed in - or wouldn't update if there was no difference. A note
about the last statement: If a Supplier object has the same
unique_id, and all other fields (in `defaults`) are the same as
well, logically there is no difference between updating and not
updating – the result is the same. > However it just seemed to
recreate entries each time even if there were no changes. Have you
checked? How? In your create_or_update_if_diff() you seem to try
to re-invent update_or_create(), but have you actually examined
the results of the supplier, created =
Supplier.objects.update_or_create(...) call? > I think the issue
was that I wanted to: > 1) get an entry if all fields were the
same, update_or_create() updates an object with the given kwargs,
the match is not made against *all* fields (i.e. for the match the
fields in `defaults` are not accounted for). > 2) or create a new
entry if it didn't find an existing entry with the unique_id > 3)
or if there was an entry with the same unique_id, update that
entry with remaining > fields. update_or_create() should achieve
this. It's hard to tell more without additional information, but
https://docs.djangoproject.com/en/1.8/ref/models/querysets/#update-or-create
<https://docs.djangoproject.com/en/1.8/ref/models/querysets/#update-or-create>
explains the function well, including how it works. If you work
through this in small steps, check examples and their
(intermediate) results, you should be able to find what the
original problem was. Best regards, Carsten
-- You received this message because you are subscribed to the Google
Groups "Django users" group. To unsubscribe from this group and stop
receiving emails from it, send an email to
django-users+unsubscr...@googlegroups.com
<mailto:django-users+unsubscr...@googlegroups.com>. To post to this
group, send email to django-users@googlegroups.com
<mailto:django-users@googlegroups.com>. Visit this group at
http://groups.google.com/group/django-users. To view this discussion
on the web visit
https://groups.google.com/d/msgid/django-users/9b529e2d-7e2b-4194-a77c-8434efe6205d%40googlegroups.com
<https://groups.google.com/d/msgid/django-users/9b529e2d-7e2b-4194-a77c-8434efe6205d%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Django
users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-users/563CA244.3000000%40gmail.com.
For more options, visit https://groups.google.com/d/optout.