Create a Computed Field?

In my custom content have three fields :
E.g.-

number of = 4
price = $ 2
Sub Total = 4 * 2

How to make the subtotal field as computed field and how to implement it.?

I would personal write an event subscriber zope.lifecycleevent.interfaces.IObjectModifiedEvent doing the math.

https://4.docs.plone.org/external/plone.app.dexterity/docs/advanced/event-handlers.html

1 Like

In my experience with this problem type, it is a good idea to make design decisions about:

  1. when you want this computed — at time of save, or on time of subsequent access?
  2. If on-access, how expensive is the calculation? Is this something you want to define some caching for lookup?
  3. Where do you want to display this?
    a. Do you need the result available in catalog metadata, e.g. listings or other sorts of things?
    b. do you intend to show this value on the display form (the view) of the object?

For the at-save-time solution, an event subscriber like Andreas mentions is the way to go — and quite frankly, this is probably the least-complexity, least-coding solution to the problem.

I have implemented computed fields for the on-access using behaviors; for this, there are multiple discussions and examples searchable on this site from previous threads. This typically involves:

  1. creating a behavior interface with fields you want
  2. using autoform directives to make the fields you care about hidden from edit form, or possibly hidden from display form, depending on your aim (for example, I have made computed fields that are only output to plone.restapi GET requests this way).
  3. Using adapter classes for property access of the computed fields which are subclasses of plone.app.dexterity.behaviors.metadata.MetadataBase — in these adapter classes, you don't need to worry about using Zope's ComputedAttribute and can simply use normal @property decorators and still get acquisition-related stuff to play nice (which you would not be able to do on a content class without using ComputedAttribute, which is a bit picky about how it is used, and can segfault when used incorrectly).
  4. If you use this type of solution, if it does not perform as well as you like, you may need to use some caching via plone.memoize — but at the point you need this, you might consider this being better solved as a save-time problem.

All that said — given the amount of work for the latter solution, if you can use something like an event subscriber for IObjectModifiedEvent you probably end up writing less code and spending less time getting what you want.

3 Likes

A couple of thoughts:

  • if the result does not depend on the context or time but it is a mere calculation, don't store it anywhere and don't define a field. Just do the maths when you need the result. You can cache the maths using cache function decorators.
  • if you need just to calculate it on the browser and it is context sensitive (for example: prices of today are different from tomorrow, discounts, etc), use a javascript to fill the field and grey out the field from user input. This means you trust the user not doing tricky things in the browser.
1 Like

Slightly related:

You dont always need the field if you just want to 'show it to the users'.

If you make a view for your content type you can put the logic in the view itself.
I use this when field 'A' is a date and 'field B' is a number.

In the view I show 'workdays left', which is a calcualation between 'A' - today - 'holidays'.
Since this changes all the time (and I dont need to 'search for it / have it in the index'), I think it is OK to do this in the view.

If you just want to show the sum, it might even be an option to do the math in a javascript (?)

1 Like

yes i'm think about that.Where to start

If you add a view with plonecli, it will give you all the logic / code you need

If you do it manually, it would be something like this:

In the view.pt you can get the field for example with

${view/something}

And in view.py

def something(self)
    #do the math there
     return result

(note the part about 'Available mr.bob templates')

ok let me see