How to perform aggregated count within a model method

Welcome @Nneji123 !

Since we’re talking about “code style” issues here, these are all opinions. There are few real rules or requirements.

However, I would say that this function is probably in the wrong location. As a general principle and an issue of style, a model method should only work on one instance of that model, “self”.

Since this is an aggregate of data on a User, I personally would most likely make this a model method in the User model.

Something like this: (Untried, unverified, and may not be syntactically correct)

# In the User model
def calculate_total_steps(self):
    return (
        self.objects.aggregate(total_steps=Sum("dailylog__steps_count", default=0))["total_steps"]
    )

However, if you’re not using a custom User model where it’s easy to add this, you might want to add this to your User’s profile model. Or, if you have a number of methods like this to be added to the User model without needing to change the User model itself, you could create a Proxy model for these methods.

You could also add this as a Manager method on the DailyLog manager. (Because this is a value associated with a user and not an arbitrary set of DailyLog instances, I consider this the least desirable option - but still better than the model method version.)

From the Manager docs:

Adding extra Manager methods is the preferred way to add “table-level” functionality to your models. (For “row-level” functionality – i.e., functions that act on a single instance of a model object – use Model methods, not custom Manager methods.)

As a purely personal side note: I’d think about expanding the validation range of your glucose readings unless you’re working with specific models that only generate readings in that range. I have seen multiple readings taken outside those ranges where the individuals involved are still lucid and functional - especially on the high side.

1 Like