Django моделей не обновляются - PullRequest
1 голос
/ 13 января 2020

Я создал систему купонов, в которой каждый пользователь изначально имеет баланс 500 в таблице сотрудников. Я хочу уменьшить этот баланс на сумму, указанную пользователем в формах html. Ниже приведены мои файлы:

Models.py

from django.db import models
from django.contrib.auth.models import User
import django
import datetime
# Create your models here.



class vendor(models.Model):
    id = models.CharField(max_length=20, primary_key=True)
    name = models.CharField(max_length=30)

class employee(models.Model):
    name = models.OneToOneField(User, on_delete=models.CASCADE)
    id = models.CharField(max_length=20, primary_key=True)
    balance = models.IntegerField(default=0)

class transaction(models.Model):
    vendor_id = models.ForeignKey(vendor, on_delete=models.CASCADE)
    emp_id = models.ForeignKey(employee, on_delete=models.CASCADE)
    debit = models.IntegerField()
    credit = models.IntegerField()
    timestamp = models.DateField(("Date"), default=datetime.date.today)

views.py

def updatingBalance(request):
    if request.method=="POST":
        ven_id = request.POST["groupOfDefaultRadios"]
        amount = request.POST["amt"]
        x = employee.objects.get(name = request.user)
        x.balance = x.balance - int(amount)
        v = vendor.objects.get(id=ven_id)
        w = employee.objects.get(id=x.id)
        transaction.objects.create(vendor_id = v, emp_id=w,debit=amount,credit=0)
        y = employee.objects.get(name = request.user)
        #print(y.balance)
        return render(request, 'profiles/userLogin.html', {'model':employee})
    return render(request, 'profiles/userLogin.html')

html форма:

{% if model %}
    <h3>Balance amount is {{ model.balance }}</h3>
{% endif %}
    <h3>Select vendor to pay!</h3>
    <br>
<form method="POST" action="/profiles/userLogin/">
        <div class="custom-control custom-radio">
              <input type="radio" class="custom-control-input" id="defaultGroupExample1" name="groupOfDefaultRadios" value="1">
              <label class="custom-control-label" for="defaultGroupExample1">Vendor 1</label>
            </div>

            <div class="custom-control custom-radio">
              <input type="radio" class="custom-control-input" id="defaultGroupExample2" name="groupOfDefaultRadios" value="2">
              <label class="custom-control-label" for="defaultGroupExample2">Vendor 2</label>
            </div> 
        <input type="" class="form-control" id="amount1" name="amt" aria-describedby="emailHelp" placeholder="Enter amount">
        <br>
        <button type="submit" class="btn btn-primary">Submit</button>

    </form> 

Куда я иду не так? Как обратиться к модели сотрудника напрямую? Я понимаю, что x может не правильно ссылаться на модель. Также мне нужно показать баланс на html. Как этого достичь?

1 Ответ

1 голос
/ 13 января 2020

Причина, по которой это не работает, заключается в том, что вы никогда не .save() свой Employee объект. Кроме того, вы должны перенаправить в случае успешного запроса POST для реализации шаблона Post / Redirect / Get [wiki] .

from django.shortcuts import redirect

def updatingBalance(request):
    if request.method=="POST":
        ven_id = request.POST["groupOfDefaultRadios"]
        amount = request.POST["amt"]
        x = employee.objects.get(name=request.user)
        x.balance = x.balance - int(amount)
        <b>x.save()</b>
        v = vendor.objects.get(id=ven_id)
        w = employee.objects.get(id=x.id)
        transaction.objects.create(vendor_id=v, emp_id=w, debit=amount, credit=0)
        <b>return redirect(updatingBalance)</b>
    <b>y = employee.objects.get(name = request.user)</b>
    return render(request, 'profiles/userLogin.html', {'model': y})

При этом я Настоятельно советуем , а не хранить баланс в модели Employee. Это создаст много проблем, таких как условия гонки , чтобы поддерживать баланс правильно обновленным.

Вместо этого вы можете сделать аннотацию, которая рассчитывает для сотрудника баланс с помощью:

class EmployeeManager(models.Manager):

    def get_queryset(self):
        return super().get_queryset().annotate(
            <b>balance=Sum(F('transaction__credit')-F('transaction__debit'))</b>
        )

class Employee(models.Model):
    name = models.OneToOneField(User, on_delete=models.CASCADE)
    id = models.CharField(max_length=20, primary_key=True)
    # <i>no</i> balance
    <b>objects = EmployeeManager()</b>

Здесь мы, таким образом, рассчитаем агрегат по связанным Transaction объектам.

В этом случае представление будет таким:

from django.shortcuts import redirect

def updatingBalance(request):
    if request.method=="POST":
        ven_id = request.POST["groupOfDefaultRadios"]
        amount = request.POST["amt"]
        x = employee.objects.get(name=request.user)
        v = vendor.objects.get(id=ven_id)
        transaction.objects.create(vendor_id=v, emp_id=x, debit=amount, credit=0)
        <b>return redirect(updatingBalance)</b>

    y = employee.objects.get(name=request.user)
    return render(request, 'profiles/userLogin.html', {'model': y})

Итак, мы делаем не нужно обновлять поле баланса, оно просто обновляется путем добавления транзакции.

Примечание : обычно модели Django, как и все классы в Python имя дано в PerlCase , а не snake_case , поэтому оно должно быть: Employee вместо employee.

Примечание : когда вы передаете объект в шаблон, то есть , а не модель, это объект модели. Таким образом, вы можете изменить имя переменной с 'model' на 'employee'.

...