[Answered ]-Foreign method access in django template

2👍

✅

As you are using a ListView to display your products there’s several things to notice:

  • get_context_data() must return a dictionary: return context is missing
  • super().get_context_data should be called with *args,**kwargs incase you decide to subclass the ProductListView at a later point in time.
  • super().get_context_data will contain a object_list key which contains the list of objects returned by get_queryset(), in your case objects of class Product.

When accessing a property from a template, django will attempt to call it without parameters if it is callable. This is often useful e.g.: for {{ request.user.is_authenticated }} or product.brand.brandimages.all

Your template should look like this:

product_list.html

{% for product in object_list %}
    <div class="rightpart">
        <div class="prodbrand h2">
            <h1>{{ product.brand }}</h1>      
            <div class="brandlogo">    
                {% for image in product.brand.brandimages.all %}
                    <img src="{{image.image.url}}"/>
                {% endfor %}
            </div><!-- End brandlogos -->
        </div><!-- End prodbrand -->
        <div class="prodtitle">
            <h2>{{ product.title }}</h2>
        </div>
    </div><!-- End rightpart -->
{% endfor %}

Take into account that this will incur several database lookups from the template. You generally want to avoid the case that your presentation layer reaches into the database, which is why you should prefer to do the database lookup in the corresponding View. Also for property access consider using select_related and prefetch_related as appropriate to avoid unneeded database queries.

views.py

class ProductListView(ListView):

    model = Product
    queryset = Product.objects.all().active()

    def get_context_data(self, *args, **kwargs):
        context = super(ProductListView, self).get_context_data(*args, **kwargs)
        context["now"] = timezone.now()
        return context

    def get_queryset(self, *args, **kwargs):
        # We call super() for potential subclasses
        queryset = super(ProductListView, self).get_context_data(*args, **kwargs)
        queryset.prefetch_related('brand__brandimages')
        return queryset

Leave a comment