Home > Software engineering >  How to save form data to two separate database tables in Django
How to save form data to two separate database tables in Django

Time:04-21

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" >

        </form>

CodePudding user response:

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')

CodePudding user response:

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>

CodePudding user response:

  1. account_number should be unique: unique=True
  2. You have to control of fitness of transactions and current amount. If amount change operation was failed non-completed transaction must be deleted
  3. 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.
  4. Account.objects.filter(account_number=account_number) will return list of accounts but you need only one account and account_number have to be unique (see ①), so better to use get instead of filter. It will return only one object or rise NotFound error
  5. You have to use ForeignKey for Trans linked to Account.id to 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}
        )
  • Related