取款系统在 OnetoOneField 中出现 IntegrityError。第一次一切正常然后出现错误

Money withdraw System got IntegrityError in OnetoOneField. All Works ok for first time then gets error

我的 model.py 中有三个 table - AccountwithdrawtaxDetails。我在帐户 table 中有一个已归档的总金额 (total_amnt_WoP)。场景是,当我尝试提取金额时,它会减少总金额并从中减少一些税(提取金额的 10%)并且每次都会保存在 taxDetails table 中.我试图在 table.

中存储总税额

在我的情况下,它第一次提取时工作正常(在 taxDetails table 中节省税款)。但是当我第二次尝试退出时,它得到:

IntegrityError.(IntegrityError at /account_balance/withdraw/, UNIQUE constraint failed: account_balance_taxdetails.user_id)

当我从 withdraw table (withdraw.objects.all().delete()) 或 taxDetails (taxDetails.objects.all().delete()) table 中删除所有对象时,它工作正常,但只是第一次。那么有什么解决办法呢?

这是我的 models.py 文件:

class Account(models.Model):
    purchase_amnt=models.FloatField()
    ref_amnt=models.FloatField()
    prantic_amnt=models.FloatField()
    middle_amnt=models.FloatField()
    ehp_amnt=models.FloatField()
    esp_amnt=models.FloatField()
    incentive_amnt=models.FloatField()
    user=models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
    total_amnt_WoP= models.FloatField()


class withdraw(models.Model):
    account=models.ForeignKey(Account, on_delete=models.CASCADE)
    user=models.OneToOneField(User, blank=True, null=True, on_delete=models.CASCADE)

    prev_amnt=models.FloatField(blank=True, null=True, default=0)
    current_amnt=models.FloatField(blank=True, null=True, default=0)
    adjast_amnt=models.FloatField(blank=True, null=True, default=0)
    requisation_amnt=models.FloatField(blank=True, null=True, default=0)


    total_cashout_amnt=models.FloatField(default=0)
    transaction_id=models.CharField(max_length=100,blank=True, null=True)
    status=models.BooleanField(default=False)

    #purchase percentage
    prev_pur_tot=models.FloatField(blank=True, null=True, default=0)
    cashout_pur_tot=models.FloatField(default=0)
    current_pur_tot=models.FloatField(blank=True, null=True, default=0)
    created_at=models.DateTimeField(auto_now_add=True)
    modified_at=models.DateTimeField(auto_now=True)


class taxDetails(models.Model):
    withdra=models.ForeignKey(withdraw, on_delete=models.CASCADE, null=True)
    user=models.OneToOneField(User, null=True, on_delete=models.CASCADE)

    tax_prev=models.FloatField(default=0)
    tax_curr=models.FloatField(default=0)
    tax_amount_tot=models.FloatField(default=0)

    tax_id=models.CharField(max_length=100)
    tax_pay_date=models.DateTimeField(auto_now=True)
    tax_info_law=models.CharField(max_length=155, blank=True, null=True)
    tax_given_area=models.CharField(max_length=100,blank=True, null=True)
    tax_medium=models.CharField(max_length=100, blank=True, null=True)
    tax_description=models.CharField(max_length=100, blank=True, null=True)

views.py 文件:

from django.contrib import messages
from .models import Account, withdraw, tax, taxDetails
import datetime
from django.utils import timezone
from .forms import withdrawForm
from django.contrib.auth.models import User



#calculating total amount
def accountBalanceCalculation(request):
    acc=Account.objects.all()

    for i in acc:
        obj=Account.objects.get(id=i.id)
        pur=i.purchase_amnt
        ref=i.ref_amnt
        prantic=i.prantic_amnt
        middle=i.middle_amnt
        ehp=i.ehp_amnt
        esp=i.esp_amnt
        incentive=i.incentive_amnt
        totalamnts=(incentive+esp+ehp+middle+prantic+ref+pur)

        obj.total_amnt_WoP=totalamnts
        obj.save()

        # Taking additional values from account table to withdraw table
        obj2=withdraw()
        obj2.account=obj
        obj2.user= i.user
        obj2.prev_amnt= totalamnts
        obj2.current_amnt= totalamnts
        obj2.prev_pur_tot = pur
        obj2.save()

    return render(request,'account_balance/show.html')


def withdrawView(request):
    tt=Account.objects.filter().values_list('total_amnt_WoP')
    ttt=tt[0]

    if request.method == "POST":
        form=withdrawForm(request.POST)
        if form.is_valid():
            requisation_amnt=form.cleaned_data['requisation_amnt'] # withdraw amount
            print('---------------------requisation_amnt to withdraw --------------')
            print(requisation_amnt)

            obj=withdraw.objects.filter(user__id=request.user.id).first()

            # purchase percenetage calculated for 10%
            purchase_percentage=(obj.prev_pur_tot/obj.prev_amnt)*100
            print("purchase_percentage checkup for 10%")
            print(purchase_percentage)

            if purchase_percentage>=10 and obj.prev_amnt>=1: #check the conditions for withdraw
                transaction_id='1kfTxx56jlj' #Static input from admin

                obj.transaction_id = transaction_id
                obj.requisation_amnt=requisation_amnt

                temp_amt = obj.total_cashout_amnt + requisation_amnt 
                obj.total_cashout_amnt= temp_amt
                obj.current_amnt= obj.prev_amnt - temp_amt
                

                #Cutting the tax 10 %
                tax_percentage_amnt=(10/100)* requisation_amnt
                after_tax_bal=requisation_amnt- tax_percentage_amnt
                print("------------ after_tax_The_balance_is -------------:")
                print(after_tax_bal)

    
                abc=User.objects.get(id=request.user.id)
                obj3=taxDetails()
                obj3.user=abc
                obj3.withdra=obj
                obj3.tax_prev= tax_percentage_amnt
                obj3.tax_curr= tax_percentage_amnt
                obj3.tax_amount_tot= obj3.tax_amount_tot + tax_percentage_amnt
                obj3.save() # This line cases the error, every time...



                x = obj.prev_pur_tot
                pur_per_amnt= (10/100)* x

                print("-------------- purchase amnt in 10 percent scale--------")
                print(pur_per_amnt)


                y = obj.cashout_pur_tot + pur_per_amnt
                obj.cashout_pur_tot =  y
                obj.current_pur_tot= x - y
                obj.save()
                # obj.modified_at=timezone.now()
                messages.success(request, 'Your request is accepted!')
                return redirect('/account_balance/withdraw/')

        else:
            print("error")

    else:
        form=withdrawForm()
    
    context={
        'form': form,
        'ttt': ttt,
    }

    return render(request,'account_balance/withdraw.html', context)

form.py 文件:

from .models import Account, withdraw

class withdrawForm(forms.ModelForm):
    class Meta:
        model = withdraw
        fields = ['requisation_amnt']

模板:

{% extends 'basic.html' %}
{% load crispy_forms_tags %}
{% block body %}

<div class="card mt-5">
    <div class="card-body">
        <div class="col-md-6 offset-md-3">
            <form action="" method="post">
                {% csrf_token %}
                {{form|crispy}}
                
                <button type="submit" class="btn btn-primary">withdraw</button>
            </form>
        </div>

    </div>
</div>

{% endblock body %}

url.py 文件:

from .views import accountBalanceCalculation, withdrawView

app_name='account_balance'

urlpatterns = [
    path('accntbal/', accountBalanceCalculation, name="accntbal"),
    path('withdraw/', withdrawView, name="withdraw"),
]

# http://127.0.0.1:8000/account_balance/accntbal/
# http://127.0.0.1:8000/account_balance/withdraw/

问题出在你的代码中,当你第一次添加记录时,它会保存在你的数据库中,但接下来当你为具有相同 ID 的同一用户添加新记录时,它会给出 UNIQUE constraint failed: 的错误,你必须更新它而不是添加它。

例如,您必须在添加针对同一用户或新用户的记录之前进行检查

try:
  if User.objects.get(id=request.user.id).exists():
     update data...
  else:
     create new record..
except Exception as e:
  print('Error : ',e)