'How to save form data to two separate database tables in Django
How would I save data from a form in Django to two separate database tables. The data would be saved to one table and also used to update the balance in another table. The first table would have a column called amount and the data would be saved to that column. The other table would have a column called current_balance and the data from the form would be added to the balance in that column.
These are my models:
class Account(models.Model):
name = models.CharField('Account Name', max_length=120, null=True)
account_number = models.CharField('Account Number', max_length=20, null=True)
DOB = models.DateField('Date of Birth', null=True)
address = models.CharField('Address', max_length=120, null=True)
contact_number = models.IntegerField('Contact Number', null=True)
opening_balance = models.IntegerField('Opening Balance', null=True)
current_balance = models.IntegerField('Balance', default=0, null=True)
def __str__(self):
return str(self.name)
class Trans(models.Model):
name = models.CharField('Name', max_length=120)
account_number = models.CharField('Account Number', max_length=120)
amount = models.IntegerField('Amount')
def __str__(self):
return str(self.name)
This is my view:
def deposit(request):
submitted = False
if request.method == "POST":
amount = request.POST.get('amount')
account_number = request.POST.get('account_number')
amount=int(amount)
Trans.objects.create(amount=amount)
d = Account.objects.filter(account_number=account_number)
new_balance = d.current_balance + amount
Account.objects.update(current_balance=new_balance)
return render(request,'accounts/deposit.html', {'message':'amount&balance saved'})
return render(request,'accounts/deposit.html')
This is the html:
<form action="" method=POST>
{% csrf_token %}
<input id="account_name" type="text" name="account_name" required>
<input id="account_number" type="text" name="account_number" required>
<input id="amount" type="text" name="amount" required>
<input type="submit" value="Submit" class="btn btn-secondary">
</form>
Solution 1:[1]
It looks like you already saved the amount to the Trans table already. Now you need to first find the account, and since I assume there is only one account with the account number you should use get instead of filter. I used get_object_or_404 so that if the account is not shown a page not found error will be given instead of an ObjectDoesNotExistError. Once the account is found, add the amount to the current balance of that account, then save it.
def deposit(request):
submitted = False
if request.method == "POST":
amount = request.POST.get('amount')
account_number = request.POST.get('account_number')
amount=int(amount)
Trans.objects.create(amount=amount)
account = get_object_or_404(Account, account_number=account_number)
account.current_balance = account.current_balance + amount
account.save()
return render(request,'accounts/deposit.html', {'message':'amount&balance saved'})
return render(request,'accounts/deposit.html')
Solution 2:[2]
You can do this easily like that:
in models.py
from django import models
class Amount(models.Model):
amount = models.CharField(max_length=100)
class Balance(models.Model):
balance = models.CharField(max_length=100)
in views.py
from .models import Amount, Balance
def form_view(request):
if request.method == "POST":
amount = request.POST.get('amount')
balance = request.POST.get('balance')
Amount.objects.create(amount=amount)
Balance.objects.create(balance=balance)
return render(request,'home.html', {'message':'amount&balance saved'})
return render(request,'home.html')
in HTML:
<form method="POST">
<input id="amount" type="text" name="amount" required>
<input id="balance" type="text" name="balance" required>
<input type="submit" value="OK">
</form>
Solution 3:[3]
account_numbershould be unique:unique=True- You have to control consistency of transactions and current amount. If amount change operation was failed non-completed transaction must be deleted
- Usually amount can't be changed without transaction. You have to implement method that will create transaction every time when amount changed automatically. That will allow to skip transaction check every time when balance changed for developers who will continue developing after you.
Account.objects.filter(account_number=account_number)will return list of accounts but you need only one account andaccount_numberhave to be unique (see ?), so better to usegetinstead offilter. It will return only one object or riseNotFounderror- You have to use
ForeignKeyforTranslinked toAccount.idto create relationship between tables.
Models are:
from django.db import transaction, models
class Trans(models.Model):
name = models.CharField('Name', max_length=120)
account_number = models.CharField('Account Number', max_length=120)
amount = models.IntegerField('Amount')
class Account(models.Model):
...
account_number = models.CharField('Account Number', unique=True, max_length=20, null=True)
...
current_balance = models.IntegerField('Balance', default=0, null=True)
# transaction atomic allows to group changes in DB
# if save operation will fail transaction creation will be also restored
@transaction.atomic
def apply_deposit(self, amount: int):
# create new deposit transaction
Trans.objects.create(
name="I'dont know what means name for transaction",
amount=amount,
account_number=self.account_number
)
# update balance
self.current_balance += amount
self.save()
deposit method:
from django.shortcuts import render
from django http import HttpReposne
def deposit(request):
if request.method == "POST":
amount = int(request.POST.get('amount'))
account_number = request.POST.get('account_number')
# get affected account number
try:
acc = Account.objects.get(account_number=account_number)
except Account.DoesNotExist:
return HttpResponse('Account not found', status=404)
# proceed deposit transaction
acc.apply_deposit(amount)
return render(
request,
'accounts/deposit.html',
{'message':'amount&balance saved', 'current_balance': acc.current_balance}
)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | raphael |
| Solution 2 | enes islam |
| Solution 3 |
