-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there a way to update a computedfield's last change? #128
Comments
Not directly, but you can create a dependent datetime field, that updates from changes on class SomeModel(ComputedFieldsModel):
fieldA = ...
@computed(..., depends=[('self', ['fieldA'])])
def comp(self):
# do something with self.fieldA
return ...
@computed(models.DateTimeField(), depends=[('self', ['comp'])])
def comp_last_changed(self):
return timezone.now() Edit: I am currently not sure, if the evaluation will be skipped if Edit2: Nope this wont work in that case, as the mro evaluation does not stop on non-changes: django-computedfields/computedfields/resolver.py Lines 544 to 548 in e734075
I think this could be patched in, so far strict updating was no issue, thus the code will eval the function if in doubt, which make the approach above not working correctly. |
🤔 forgot to add that my or in the original EDIT1: i just saw hmm i guess there's no easy way to do this? |
Right, thats not as easy as it sounds - currently the update resolver give no guarantees not to update a field in question. It resorts to "if in doubt - update anyway", since keeping values in sync is more important than anything else. There is still a custom solution possible here (I admit its not nice) - the only field during cf updates, that knows whether class SomeModel(ComputedFieldsModel):
fieldA = ...
comp_last_changed = models.DateTimeField()
@computed(..., depends=[('self', ['fieldA'])])
def comp(self):
# grab old value
old_value = self.comp
# do something with self.fieldA
new_value = ...
# update conditionally on value change
if old_value != new_value:
self.comp_last_changed = timezone.now()
if self.pk:
self.save(update_fields=['comp_last_changed'])
return new_value The Edit: class SomeModel(ComputedFieldsModel):
fieldA = ...
comp_last_changed = models.DateTimeField()
@computed(..., depends=[('self', ['fieldA'])], may_update=['comp_last_changed'])
def comp(self):
# grab old value
old_value = self.comp
# do something with self.fieldA
new_value = ...
# update conditionally on value change
if old_value != new_value:
self.comp_last_changed = timezone.now()
return new_value Note the additional kwarg |
Thinking again about the issue the ideas above are not ideal for these reasons:
Imho a better and more versatile approach is to get signals from the update resolver done, see #58. So far I did not push that PR forward, as mass updates as normally done by the resolver create some issues about the right signal abstraction, like what types of signals we gonna need and in which transaction context the signal handlers should run. And for strict post signals (emitted after the resolver finished all transactions) it creates a lot of state to be held in memory. Putting aside these issues for a moment, with the right signals something like this should be possible: @receiver(post_change_computedfields, sender=SomeModel, field='comp')
def my_handler(sender, field, queryset, **kwargs):
# queryset now contains only instances, where comp changed
# do whatever you like based on those changes
... |
let say
so i want a
comp_last_changed
which is a datetimehow do I do this?
The text was updated successfully, but these errors were encountered: