This is certainly reasonable over all.
I would point out, however, that manager instance, "self" in your Transaction_list and points_total methods, *is* Transaction.object, so (assuming that you keep them as manager methods), you could just use "self.filter...". Further, in the interests of not having duplicate code to maintain, you could implement points_total using "self.Transaction_list(thisUser).aggregate...". A style point, while it is customary to use an initial upper case letter on model and manager (and other class) names, method names, especially those using underscores as word separators, are usually all lower case. But, too, since it is part of a TransactionManager, it is a bit redundant to name the method Transaction_list. You could call it just "list", but perhaps "for_user" is clearer, allowing you to say (in the view) "Transaction.objects.for_user(request.user)", which is nearly the simple English for what you are doing.
It is possible, but not conventional, to create these methods as classmethods on the Transaction class, rather than requiring the implementation of a custom manager class, e.g.:
@classmethod
def for_user(cls, thisUser):
return cls.objects.filter(user=thisUser)
You would use this in the view like so:
thisPoints = Transaction.for_user(request.user)
There is a mild preference for the manager approach, since it doesn't pollute the model name space. A model already has an "objects" attribute, so accessing the manager doesn't require a new attribute. Using the classmethod means that there is one more attribute on a model instance, which should largely be about the instance (table row), rather than about accessing instances. Not, however, a big deal.
But both of these methods are so simple that hand coding them in the view has appeal. It makes the code local, rather than forcing the reader to find the manager code to know for sure what's happening. If the function were more complex, or if it is used in more than one place, then the separate manager methods are to be preferred.
And note that you can use a queryset multiple times without having to recreate it.
@login_required
def history(request):
thisPoints = Transaction.objects.filter(user=request.user)
totalPoints = thisPoints.aggregate(total_points=models.Sum('points'))
...
The use of "thisPoints" in calculating "totalPoints" doesn't change "thisPoints". You can still enumerate it in the template, and get the same result.
Bill