Django - Show list of purchases in user's profile - include template with list from another app

1.2k Views Asked by At

I'm doing a project with Django and I'm using PayPal subscriptions. When you buy a product it saves the details in the Purchases table (by the way, it writes the purchase 3 times in the DB, but that's for another question). Now I'm trying to show a list of purchases in the user's profile template. I have a purchases template with the list and it works when I see it through its own URL, but whenever I try to show it in other templates it's just blank.

This is my structure:

  • Apps: Account, Product, PayPal
  • Models: User(custom), Product, Purchase
  • Templates: profile, products, purchases, paypal_return/cancel,...
  • Views: register, login, logout, all_products, paypal_return/cancel,...
  • templatetags/products_extra: paypal_form_for, and right now a simple_tag with purchases_list (I also tried with just a view in products/views.py)

And my questions are:

  1. Should I have a different app for purchases?

  2. What is the best way to build the purchases list and show it in a template in another app? I've read loads of posts and documentation and tried just including the template {% include.. %}, with simple_tags, with template inheritance, inclusion tags... but I cannot make it work.

Below is the code I have right now.

Thank you in advance!

models.py

class Purchase (models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='purchases')
    product = models.ForeignKey(Product)
    license_end = models.DateTimeField(default=timezone.now)

templatetags/product_extras.py

@register.simple_tag
def purchases_list(request):
    purchases = Purchase.objects.all()
    return render(request, 'products/purchases.html', {'purchases': purchases})

urls.py

    url(r'^purchases/$', product_extras.purchases_list, name='purchases'),

purchases.html

    <p>PURCHASES</p>
        {% for purchase in purchases %}
            <p>{{purchase.id}}-{{ purchase.product }} - {{ purchase.license_end }}</p>
        {% endfor %}

profile.html

    {% include "products/purchases.html" %}
2

There are 2 best solutions below

4
On BEST ANSWER

Based on your info, my solution to your problem is to change your profile view to this:

def profile(request):
    purchases = Purchases.objects.all()
    return render(request, 'account/profile.html', {'purchases':purchases})

When you include a template in another template you have to think that it is only a copy/paste operation. In order for it to render properly you have to provide the appropriate context variables, in this case purchases.

In addition, I believe you may want to improve your view further by showing only the purchases of the current logged user.

Edit:

If you want to do it using template tags, you may take a look at inclusion tags. They seem perfect for your use case.

I can not think of a way to do this using template inheritance. Inheritance is more suitable for things like defining a fixed header and footer.

1
On

In your purchases.html remove the template tags:

{% block purchasess %}{% endblock %}