Home > OS >  Show all items of an invoice - django
Show all items of an invoice - django

Time:03-17

I would like to get all items belonging to an invoice and show them to a template without success. What i have done so far is the following:

I have two models:

class Invoice(models.Model):

    PAYMENT_OPTIONS = (
        ('CASH', _('CASH')),
        ('DEPOSIT', _('DEPOSIT')),
        ('CARD', _('CARD')),
    )

    INVOICE_TYPE = (
        ('Service', _('Service')),
    )

    invoice_number = models.CharField(max_length=7, unique=True, default='INV4898')
    invoice_user = models.ForeignKey(Account, on_delete=models.CASCADE)
    invoice_type = models.CharField(max_length=30, choices=INVOICE_TYPE, default='Service')
    payment_option = models.CharField(max_length=30, choices=PAYMENT_OPTIONS)
    invoice_name = models.CharField(max_length=30, null=True, blank=True)
    vat = models.CharField(max_length=9, blank=True, null=True)
    gross_amount = models.DecimalField(max_digits=6, decimal_places=2)
    vat_amount = models.DecimalField(max_digits=6, decimal_places=2)
    net_amount = models.DecimalField(max_digits=6, decimal_places=2)
    created_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
      return f"{self.invoice_user.first_name} {self.invoice_user.last_name} - {self.invoice_number}"

class Item(models.Model):

    invoice = models.ForeignKey(Invoice, related_name='items', on_delete=models.CASCADE)
    title = models.CharField(max_length=255)
    quantity = models.IntegerField(default=1)
    unit_price = models.DecimalField(max_digits=6, decimal_places=2, default=Decimal('0.00'))
    net_amount = models.DecimalField(max_digits=6, decimal_places=2, default=Decimal('0.00'))
    vat_rate = models.CharField(max_length=10, default=0)
    discount = models.DecimalField(max_digits=6, decimal_places=2, default=Decimal('0.00'))
    is_paid = models.BooleanField(default=False)
    created_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
      return f"{self.invoice.invoice_number}"

In the views.py i have a list view like, in which i'm trying to get a list of all invoices based on invoice_number and then match each invoice_number to an invoice in items. However using below code first pring brings all invoice_number(s) and second print brings all items for all invoices, not items per invoice.

def list_invoices(request, userprofile_id):
    user_profile = get_object_or_404(Account, pk=userprofile_id)
    all_invoices =Invoice.objects.filter(invoice_user=user_profile)

    invoice_number = Invoice.objects.values_list('invoice_number')
    print(invoice_number)
    
    item_invoice = Item.objects.filter(invoice__invoice_number__in=invoice_number)
    print(item_invoice)


    context = {
        'all_invoices': all_invoices,
        'user_profile': user_profile,
        'item_invoice': item_invoice,
    }
    return render(request, 'invoices/list-invoices.html', context)

I would appreciate any help.

CodePudding user response:

You do not need to fetch the Items not the invoice_number of the Invoice. You only need to pass the invoices of the user_profile, and it might be better to also prefetch the Items:

def list_invoices(request, userprofile_id):
    user_profile = get_object_or_404(Account, pk=userprofile_id)
    all_invoices = Invoice.objects.filter(
        invoice_user=user_profile
    ).prefetch_related('items')

    context = {
        'all_invoices': all_invoices,
        'user_profile': user_profile
    }
    return render(request, 'invoices/list-invoices.html', context)

then in the template, you can access the .items, so:

<ul>
{% for invoice in all_invoices %}
    <li> {{ invoice.invoice_number }}</li>
    <ul>
    {% for item in invoice.items.all %}
        <li>{{ item.quantity }} {{ item.title }}</li>
    {% endfor %}
    </ul>
{% endfor %}
</ul>
  • Related