Как обновить баланс счета пользователя при покупке в Django View?

В качестве побочного проекта я работаю над созданием симулированного приложения для обмена криптовалют. Для первой части я просто создаю простую страницу, где пользователи могут покупать и продавать BTC за USD, и она будет обновлять их соответствующие балансы для каждого из них. Я создал форму для 'Trade' и две таблицы модели - 'Trade' и 'Portfolio.

Как настроить это так, чтобы при совершении "сделки" обновлялось количество токенов (при покупке) или количество USD (при продаже) в "портфеле", а если их нет, то создавалась новая запись?

models.py:

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Trade(models.Model):
    token_name = models.CharField(max_length=100)
    token_symbol = models.CharField(max_length=10)
    date = models.DateTimeField(default=timezone.now)
    account = models.ForeignKey(User, on_delete=models.CASCADE, related_name='trader')
    amount = models.FloatField()
    price = models.FloatField()
    type = models.CharField(max_length=15,
                              choices=(
                                  ("Market Buy", "Market Buy"),
                                  ("Market Sell", "Market Sell")))

    def id(self):
        return id(self.id)

class Portfolio(models.Model):
    token_name = models.CharField(max_length=100, unique=True, default="United States Dollar")
    token_symbol = models.CharField(max_length=10, default="USD")
    account = models.ForeignKey(User, on_delete=models.CASCADE, related_name='portfolio')
    amount_holding = models.FloatField(default="100000")

    def id(self):
        return id(self.id)

Views.py:

from django.shortcuts import render
from django.http import HttpResponse
from .models import Trade
from .models import Portfolio
from django.contrib import messages
from .filters import TradeFilter
from .forms import BuyForm
from .forms import SellForm
from django.http import HttpResponseRedirect
import datetime

def home(request):
    data = ''
    trades = Trade.objects.filter(account=request.user.id)
    myFilter = TradeFilter(request.GET, queryset=trades)
    trades = myFilter.qs
    buyform = BuyForm()
    sellform = SellForm()
    context = {
        'trades': trades,
        'myFilter':myFilter,
        'buyform': buyform,
        'sellform': sellform
    }
    if request.method == 'GET':
        if request.user.is_authenticated == False:
            messages.info(request, 'You need to register and log in to use these features')
    if request.method == 'POST':
        if request.POST.get("form_type") == 'BuyForm':
            if request.user.is_authenticated:
                buyform = BuyForm(request.POST)
                if buyform.is_valid():
                    instance = buyform.save(commit=False)
                    instance.account = request.user
                    instance.token_name = 'Bitcoin'
                    instance.token_symbol = 'BTC'
                    remove_funds = 30000 * instance.amount
                    instance.price = -abs(remove_funds)
                    instance.type = 'Market Buy'
                    instance.save()
                    return HttpResponseRedirect(request.path_info)

            else:
                messages.error(request, 'Buy error: You are not logged in')
        elif request.POST.get("form_type") == 'SellForm':
            if request.user.is_authenticated:
                sellform = SellForm(request.POST)
                if sellform.is_valid():
                    instance = sellform.save(commit=False)
                    instance.account = request.user
                    instance.token_name = 'Bitcoin'
                    instance.token_symbol = 'BTC'
                    instance.price = 30000 * instance.amount
                    instance.type = 'Market Sell'
                    instance.save()
                    return HttpResponseRedirect(request.path_info)
            else:
                messages.warning(request, 'Sell error: You are not logged in')
    return render(request, 'exchange/home.html', context)

EDIT: forms.py:

from django import forms
from django.forms import ModelForm
from .models import Trade
from .models import Portfolio

class BuyForm(ModelForm):
    class Meta:
        model = Trade
        fields = ['amount']

class SellForm(ModelForm):
    class Meta:
        model = Trade
        fields = ['amount']

Я искал в документации, но не смог найти никаких примеров.

В блоке if form.is_valid(): просто добавьте следующий блок после instance.save() и настройте по необходимости.

portfolio, __ = Portfolio.objects.get_or_create(
    account=instance.account,
    token_name=instance.token_name
    token_symbol=instance.token_symbol
)
portfolio.amount = portfolio.amount + token_symbol // or - for the other form
portfolio.save()

я бы написал функцию для этого (быстро и грязно, чтобы вы могли видеть, что делать):

def update_portfolios(user, btc_amount, usd_amount):
    btc_portfolio, _ = Portfolio.objects.get_or_create(account=user, token_symbol='BTC', token_name='Bitcoin')
    usd_portfolio, _ = Portfolio.objects.get_or_create(account=user, token_symbol='USD', token_name='United States Dollar')
    btc_portfolio.amount_holding = btc_amount
    usd_portfolio.amount_holding = usd_amount
    btc_portfolio.save()
    usd_portfolio.save()

тогда просто вызовите функцию, указав request.user в качестве пользователя и суммы

Вернуться на верх