简体   繁体   中英

Looking for a better OOP approach

I want to update a users balance. To do this currently I have to save the Account object, consider the following view:

def refresh_balance(request):
    """
    Balance Refresh.

    The balance shown on every page is a cached balance for performance reasons.
    To get the real balance you need to re-save the account object which will refresh
    the cached value in the database.

    """
    page = request.GET['redirect']
    account = Account.objects.get(user=request.user)
    account.save()
    message_user(
        request.user,
        "Account Balance Refreshed.")
    return HttpResponseRedirect(page)

In the model.py I have the following Class Methods that does the leg work:

def save(self, *args, **kwargs):
        self.balance = self._balance()
        return super(Account, self).save(*args, **kwargs)


    def _balance(self):
        aggregates = self.transactions.aggregate(sum=Sum('amount'))
        sum = aggregates['sum']
        return D('0.00') if sum is None else sum

This to me look cumbersome, I'm re-saving to re-save (if that makes sense) and ideally I want to just call refresh() within any of my views, whenever I want. I'm no Django expert and need some advice on how to better handle this.

I have looked at static methods maybe?

def _balance(self):
        aggregates = self.transactions.aggregate(sum=Sum('amount'))
        sum = aggregates['sum']
        return D('0.00') if sum is None else sum

    @staticmethod
    def update_balance(model):
        model.balance = unsure here as I need 'self'? 

Then just calling Account.update_balance(Account) ?????

Any advice? PS this is not an open question, it's clear what I'm trying to do and what I'm after. Thanks :)

Stalk's answer is good but I prefer it when methods do one thing and one thing only. As it is now, .refresh() takes care of two things. Computing balance and saving. I would break it up even further by implementing the .refresh() method but in the view do this. (Also I would name it refresh_balance instead of refresh, refresh implies that we refresh the whole account).

account.refresh_balance()
account.save()

This makes it so that the logic for .refresh_balance() can change but the .save() would be left alone to do what it makes best. Save your model to the database.

This will also make your code less prone to bugs. We'll also follow The Zen of Python by: "explicit is better than implicit".

It is easy to create custom model method, for example refresh :

class Account(models.Model):
    # ... some fields

    def refresh(self):
        # do needed stuff
        self.balance = self._balance()
        self.save()

And then just call it:

# ...
account = Account.objects.get(user=request.user)
account.refresh()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM