Django中未更新模型字段值

2024-09-21 05:48:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在建设这个投票平台,用户将不得不投票。他们将输入想要购买的票数,然后付款。成功付款后,他们刚购买的票数应添加到数据库中的旧票数中

例如,假设一个用户以10美元的价格购买了2张选票,并且已经有3张选票,那么2应该被添加到3中,使其成为5张

我的问题是,用户投票中增加了10美元

models.py

class Nomination(models.Model):
    Fullname = models.CharField(max_length=120)
    Nominee_ID = models.CharField(max_length=100)
    Category = models.ForeignKey(Category, on_delete=models.CASCADE)
    image = models.ImageField(upload_to='nominations_images')
    slug = models.SlugField(max_length=150)
    votes = models.IntegerField(default=0)
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.Fullname
 
views.py

def nomination_payView(request, slug):
        if request.method == 'GET':
            model = get_object_or_404(Nomination, slug=slug)
            template_name = 'Payment.html'
            context = {
                'nomination': model
            }
            return render(request, 'Payment.html', context)
        elif request.method == 'POST':
            amount = (str(int(request.POST['votes']) * float(request.POST['price'])) + '0').replace('.', '')
            zeros = '0' * (12 - len(amount))
            amount = zeros + amount
            email = request.POST['email']

            url = 'https://test.theteller.net/checkout/initiate'
            transaction_id = random.randint(100000000000, 999999999999)
            data = {
                "merchant_id": "TTM-00000740",
                "transaction_id": transaction_id,
                "desc": "Payment Using Checkout Page",
                "amount": amount,
                "redirect_url": f"http://127.0.0.1:8000/process-payment/{slug}/{amount}",
                "email": email,
                "API_Key": "ZDQ2OGEyZDNjN2YzMDY5ZDVkY2MyM2U5YTRiMGI0N2Q=",
                "apiuser": "halotech5d525bfd6ead3",
            
            }
            encoded = base64.b64encode(
                b'halotech5d525bfd6ead3:ZDQ2OGEyZDNjN2YzMDY5ZDVkY2MyM2U5YTRiMGI0N2Q=')
            headers = {
                'Content-Type': 'application/json',
                'Authorization': f'Basic {encoded.decode("utf-8")}',
                'Cache-Control': 'no-cache'
            }
            res = requests.post(url, data=json.dumps(data), 
            headers=headers).json()
            print(res['checkout_url'])
            return redirect(res["checkout_url"])

def process_payment(request, slug, amount):
    trans_id = request.GET.get('transaction_id')
    status = request.GET.get('status')
    reason = request.GET.get('reason')
    transaction_id = request.GET.get('transaction_id')
    if status == 'Approved':
        transaction = SuccessfulTransactionHistory(
            nominee_name=slug,
            transaction_id=transaction_id,
            amount=amount
        )
        transaction.save()
        nomination = Nomination.objects.filter(slug=slug).values('votes')
        Nomination.objects.filter(slug=slug).update(votes=int(nomination[0]['votes']) + int(amount[:-2]))
        return redirect('/success')
    else:
        context = {
            'error': reason
        }
        transaction = FailedTransactionHistory(
            nominee_name=slug,
            transaction_id=transaction_id,
            amount=amount
        )
        transaction.save()
        return render(request, 'payment_error.html', context=context)


Tags: idurlgetreturnmodelsrequestcontextpost
1条回答
网友
1楼 · 发布于 2024-09-21 05:48:51

无需执行单独的查询来获取值(第一个)和增量(第二个)。只需使用F expression访问同一模型中的字段,并在单个操作中执行增量:

from django.db.models import F

Nomination.objects.filter(slug=slug).update(votes=F('votes') + amount)

无需将Nomination.votes强制转换为int,因为它已经是。但是如果amount是一个str(如果您在URL中接受它作为int以避免这样的转换,则更好):

Nomination.objects.filter(slug=slug).update(votes=F('votes') + int(amount[:-2]))  # The slice [:-2] was used as performed in the question. Adjust accordingly depending on what the amount really contains.

这里,目标为slug的所有Nomination对象的votes都将增加所述数量


更新

因为我们需要votes的计数,所以我们不应该在这里只接受amount,因为它已经是votes * price的乘积。我们可以做的是更改对该API的调用,并通过更改nomination_payView()来包括votes,特别是这一行:

"redirect_url": f"http://127.0.0.1:8000/process-payment/{slug}/{amount}",

例如:

"redirect_url": f"http://127.0.0.1:8000/process-payment/{slug}/{amount}?votes={request.POST['votes']}",

或:

"redirect_url": f"http://127.0.0.1:8000/process-payment/{slug}/{amount}/{request.POST['votes']}",
  • 您将选择什么取决于端点https://test.theteller.net/checkout/initiate可能处理的内容,因为它将执行重定向

然后在这个process_paymentAPI中,我们可以直接从查询参数访问该计数:

Nomination.objects.filter(slug=slug).update(votes=F('votes') + int(request.GET['votes']))

或者,如果从路径参数中选择了第二个选项

Nomination.objects.filter(slug=slug).update(votes=F('votes') + votes)  # Assuming you defined the URL as something like <path("process-payment/{str:slug}/{int:amount}/{int:votes}", ...> and the view function as <def process_payment(request, slug, amount, votes):>

相关问题 更多 >

    热门问题