On Thursday 16 November 2017 14:08:20 Sjoerd Job Postmus wrote: > I disagree with not being able to calculate it locally (without the > database): such a calculation depends on other fields. What if a dependent > field is updated, but the object is not yet saved. What should the value > be? > > >>> c.age, c.is_adult > > 17, False > > >>> c.age = 40 > >>> c.age, c.is_adult > > 40, False > > Would not make sense to me. >
While I agree with the gist of this argument, I don't believe in parallel computations -- that is, having some database-definition of a computed column emulated in Python. Such computations always end up slightly different in some edge cases (different precision, different rounding rules, different timezones between webserver and database server, etc) and this can lead to obscure heizenbugs and weird, hard-to-track data corruptions. I see three solutions: 1) Make all computations in Python. This means the feature can be supported only on databases which can run Python as part of their queries; I'm not quite sure about the details, but I think PG can. I'm certain none of the other core databases can, perhaps MSSQL can with IronPython. 2) Just invalidate all calculated columns as soon a change in the model occurs. So then, >>> c.age, c.is_adult 17, False >>> c.age = 40 >>> c.is_adult StaleCalculatedFieldException 3) If we claim that the calculated field is, essentially, a declarative shorthand for .annotate(), then treat it as such -- and live with the result whcih Sjoerd Job described as nonsensical. However, to make it a little less nonsensical, we'd call the field something like "DBCalculatedField", to point out that it isn't updated automatically in the model instance. BTW, with annotate we already have that "nonsensical" behavior today, and people seem to accept it: class Teacher(models.Model): pass class Student(models.Model): teacher = models.ForeignKey(Teacher) ... >>> t = Teacher.objects.annotate(std_count=Count('student')).get(pk=1) >>> t.std_count 16 >>> Student.objects.create(teacher=t) >>> t.std_count 16 I understand that the perception may be different for calculated fields which depend purely on "in-record" fields -- but I don't see a good way to verify that property on the caclulated field definition, so I suspect the best (or, rather, least bad) solution is just to change that perception. Shai