javascript – Dynamically updating values ​​of a field depending on the choice selected in another field in Django

I have two tables.
Inventory and Invoice.

InventoryModel:

from django.db import models

class Inventory(models.Model):
  product_number = models.IntegerField(primary_key=True)
  product = models.TextField(max_length=3000, default="", blank=True, null=True)
  title = models.CharField('Title', max_length=120, default="", blank=True, unique=True)
  amount = models.IntegerField('Unit Price', default=0, blank=True, null=True)

  def __str__(self):
    return self.title

InvoiceModel:

from django.db import models
from inventory.models import Inventory

class Invoice(models.Model):
invoice_number = models.IntegerField(blank=True, primary_key=True)

line_one = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+", verbose_name="Line 1", blank=True, default="", null=True)
line_one_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_one_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_one_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_two = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+",  verbose_name="Line 2", blank=True, default="", null=True)
line_two_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_two_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_two_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_three = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+",  verbose_name="Line 3", blank=True, default="", null=True)
line_three_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_three_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_three_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_four = models.ForeignKey(Inventory, on_delete=models.CASCADE,related_name="+",  verbose_name="Line 4", blank=True, default="", null=True)
line_four_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_four_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_four_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_five = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+",  verbose_name="Line 5", blank=True, default="", null=True)
line_five_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_five_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_five_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_six = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+",  verbose_name="Line 6", blank=True, default="", null=True)
line_six_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_six_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_six_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_seven = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+",  verbose_name="Line 7", blank=True, default="", null=True)
line_seven_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_seven_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_seven_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_eight = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+",  verbose_name="Line 8", blank=True, default="", null=True)
line_eight_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_eight_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_eight_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_nine = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+",  verbose_name="Line 9", blank=True, default="", null=True)
line_nine_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_nine_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_nine_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

line_ten = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="+",  verbose_name="Line 10", blank=True, default="", null=True)
line_ten_quantity = models.IntegerField('Quantity', default=0, blank=True, null=True)
line_ten_unit_price = models.IntegerField('Unit Price(₹)', default=0, blank=True, null=True)
line_ten_total_price = models.IntegerField('Line Total(₹)', default=0, blank=True, null=True)

def __unicode__(self):
    return self.invoice_number

I have a form where the person selects an Inventory.title in the line_one. I want the line_one_unit_price to be automatically filled according to the option selected in the line_one. That is, I want the amount of that product to be displayed.

I tried using a JSON object and then sending it to the template.

views.py:

def add_invoice(request):
  form = InvoiceForm(request.POST or None)
  data = Inventory.objects.all()
  dict_obj = model_to_dict(data)
  serialized = json.dumps(dict_obj)
  total_invoices = Invoice.objects.count()
  queryset = Invoice.objects.order_by('-invoice_date')[:6]

  if form.is_valid():
    form.save()
    messages.success(request, 'Successfully Saved')
    return redirect('/invoice/list_invoice')
  context = {
    "form": form,
    "title": "New Invoice",
    "total_invoices": total_invoices,
    "queryset": queryset,
    "serialized":serialized,
  }
  return render(request, "entry.html", context)

I am not sure how I can access that JSON file in javascript? what will be the name of that JSON object? Is it possible to access that in JavaScript? How can I use it to update the price of an item in the forms dynamically? Thanks.

EDIT:

I added this in the HTML file:

    {{ data|json_script:"hello-data" }}
<script type="text/javascript">
    const data = JSON.parse(document.getElementById('hello-data').textContent);

    document.getElementById('id_line_one').onchange = function(){
        document.getElementById('id_line_one_unit_price').value = data[this.value];
    };

</script>

views.py:

def add_invoice(request):
  form = InvoiceForm(request.POST or None)
  data = serializers.serialize("json", Inventory.objects.all())
  total_invoices = Invoice.objects.count()
  queryset = Invoice.objects.order_by('-invoice_date')[:6]

  if form.is_valid():
    form.save()
    messages.success(request, 'Successfully Saved')
    return redirect('/invoice/list_invoice')
  context = {
    "form": form,
    "title": "New Invoice",
    "total_invoices": total_invoices,
    "queryset": queryset,
    "data": data,
  }
  return render(request, "entry.html", context)

The output I get when I select an item is {? I don’t know why?
screenshot

I guess it’s because the logic I used in the javascript is incorrect?

JSON File:

[{"model": "inventory.inventory", "pk": 1, "fields": {"product": "nice", "title": "Asus", "amount": 56000}}, {"model": "inventory.inventory", "pk": 2, "fields": {"product": "nice", "title": "Lenovo", "amount": 55000}}]

Edit2:

I added this in the script:

<script type="text/javascript">
    const data = JSON.parse(document.getElementById('hello-data').textContent);

    document.getElementById('id_line_one').onchange = function(){
        var line_one=document.getElementById('id_line_one').value;
        document.getElementById('id_line_one_unit_price').value = data.fields[line_one].amount;
    };

</script>

And now I am getting an Uncaught TypeError: Cannot read properties of undefined (reading '1') error. Whenever I select the object from the dropdown, It’s value is stored from 1, etc. So the first object in the list returns it’s primary key, ie, 1. I think I am accessing the fields in a wrong way.

Leave a Comment