0

I'm following a tutorial and I'm tying to show each object property (that is saved in db) in my template html file like this:

{% for obj in objects_list %}
    <p>{{ obj.name }} => {{ obj.location }} <b>timecreated</b>==> {{ obj.timestamp }} <b>time updated</b>==> {{ obj.updated }}</p>

{% endfor %}

I should get slug in url and this url

http://localhost:8000/restaurants/shomal/

/shomal/ is our slug and we must watch object detail where category is equal to = shomal

I can't see the loop result in template but when in print queryset I can see the object detail in the terminal

Why can't I reach object detail in the template for loop?

In my app view file I have

from django.shortcuts import render
from django.shortcuts import HttpResponse
from django.views import View
from django.views.generic import TemplateView, ListView
from .models import Restaurant
from django.db.models import Q


def restaurants_listview(request,):
    template_name = 'restaurants/restaurants_list.html'
    query_set = Restaurant.objects.all()
    context = {
        "objects_list": query_set
    }
    return render(request, template_name, context)


class RestaurantListView(ListView):
    template_name = 'restaurants/restaurants_list.html'

    def get_queryset(self):
        print(self.kwargs)
        slug = self.kwargs.get("slug")
        if slug:
            queryset = Restaurant.objects.filter(
                Q(category__iexact=slug)|
                Q(category__icontains=slug)
            )
            print(queryset)

        # return queryset
        else:
            queryset = Restaurant.objects.all()
        return queryset

and in django url.py file I have

from django.contrib import admin
from django.urls import path
from django.views.generic.base import TemplateView
from restaurants.views import (
    restaurants_listview,
    RestaurantListView
)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', TemplateView.as_view(template_name="home.html")),
    path('restaurants/', RestaurantListView.as_view()),
    path('restaurants/<str:slug>/', RestaurantListView.as_view()),
    path('about/', TemplateView.as_view(template_name="about.html")),
    path('contact/', TemplateView.as_view(template_name="contact.html")),
]

and this is my models file

from django.db import models


# Create your models here.
class Restaurant(models.Model):

    name = models.CharField(max_length=120)
    location = models.CharField(max_length=120, null=True, blank=True)
    category = models.CharField(max_length=120, null=True, blank=True)
    timestamp = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name
Alasdair
  • 298,606
  • 55
  • 578
  • 516
moh
  • 433
  • 10
  • 33

1 Answers1

3

By default, the ListView adds the list of objects to the template context as object_list. You currently have objects_list.

The simplest fix is to change your template to use object_list:

{% for obj in object_list %}
    <p>{{ obj.name }}</p>
{% endfor %}

Since your model is Restaurant, you can also use restaurant_list, which will make your template more descriptive:

{% for restaurant in restaurant_list %}
    <p>{{ restaurant.name }}</p>
{% endfor %}

If you don't want to use object_list or restaurant_list, another option is to set context_object_name.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • thaknyou you solved it but can you tell me why - how ListView give us object_list .. when i have objects_list above – moh Dec 14 '17 at 11:32
  • When you switch to `RestaurantListView.as_view()` in your `urls.py`, your view function `restaurants_listview` is not used any more. You can delete it. The `ListView` uses `object_list` by default, that's just the way it works. – Alasdair Dec 14 '17 at 11:41