I'm learning Django and trying to setup some dynamic pages. I've mapped url's to /restaurants and /restaurants/mexican however my html content block is not displaying anything from my queryset. Code below:
views.py
def restaurantListView(request):
template_name = 'restaurants/restaurants_list.html'
queryset = Restaurant.objects.all()
context = {
"objectList": queryset
}
return render(request, template_name, context)
class RestaurantListView(ListView):
queryset = Restaurant.objects.all()
template_name = 'restaurants/restaurants_list.html'
class MexicanRestaurantListView(ListView):
queryset = Restaurant.objects.filter(category__iexact='mexican')
template_name = 'restaurants/restaurants_list.html'
class AsianFusionRestaurantListView(ListView):
queryset = Restaurant.objects.filter(category__iexact='asian fusion')
template_name = 'restaurants/restaurants_list.html'
urls.py
from restaurants.views import (
restaurantListView,
RestaurantListView,
MexicanRestaurantListView,
AsianFusionRestaurantListView,
)
urlpatterns = [
path('admin/', admin.site.urls),
path('', TemplateView.as_view(template_name='home.html')),
path('restaurants/', RestaurantListView.as_view()),
path('restaurants/mexican/', MexicanRestaurantListView.as_view()),
path('restaurants/asian/', AsianFusionRestaurantListView.as_view()),
path('about/', TemplateView.as_view(template_name='about.html')),
path('contact/', TemplateView.as_view(template_name='contact.html')),
]
restaurants_list.html
{% extends "base.html" %}
{% block head_title %} Restaurants || {{ block.super }} {% endblock %}
{% block content %}
<h1>Restaurant List</h1>
<ul>
{% for obj in objectList %}
<li>{{ obj.name }} | {{ obj.location }}</li>
{% endfor %}
</ul>
{% endblock content %}
I expected the items of Restaurant.objects.all() to be displayed in my content block on restaurants.html, but instead nothing is displaying. Same occurs for objects.filter() on the /restaurants/mexican route.
The template variable should be object_list, not objectList.
(Note, you certainly don't need one view per restaurant type. Rather, have a view for RestaurantsByType and get the type as a URL parameter.)
'''
Just add one extra "_" in the 'category__iexact'
'''
class MexicanRestauratListView(ListView):
queryset = RestaurantLocation.objects.filter(category__iexact='mexican')
template_name = "restaurants/restaurantlocation_list.html"
class AsianFusionRestauratListView(ListView):
queryset = RestaurantLocation.objects.filter(category__iexact='asian fusion')
template_name = "restaurants/restaurantlocation_list.html"
Related
I had another post related to this but my code was complex so the communication was difficult. I completely stripped off the issue from the unnecessary details and came up with a very minimal example shown below:
templates/base.html:
<html>
<body>
<p>I am base.html</p>
{% block content %}
{% endblock content %}
</body>
</html>
templates/blog.html:
{% extends 'base.html' %}
{% block content %}
<p>I am blog.html</p>
{{ blog_list }}
{% for blog in blog_list %}
{{ blog.title }}
{% endfor %}
{% endblock %}
And blog/views.py
from django.views import generic
from .models import Blog
class BlogList(generic.ListView):
queryset = Blog.objects.filter()
template_name = 'blog.html'
# context_object_name = 'blog_list'
class BlogDetail(generic.DetailView):
model = Blog
template_name = 'blog.html'
That outputs this:
I was expecting the list of blog titles to be rendered there. I debugged the BlogList class and queryset value was this:
<QuerySet [<Blog: First Page>, <Blog: Intro>]>
So, the query is not empty. I have been completely frustrated by this issue. Anyone know what's going on?
Edit: Here is blog/urls.py:
urlpatterns = [
path('<str:parent>/<slug:slug>/', views.BlogDetail.as_view(), name='blog'),
]
And project urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('qa.urls')),
path('blog/', include('blog.urls')),
]
After some clues given by #Abdul Aziz Barkat, I realized the problem is I should be linking to the BlogDetail view instead of BlogList view. So, I changed urlpatterns of blog/urls.py to:
urlpatterns = [
path('<str:parent>/<slug:slug>/', views.BlogDetail.as_view(), name='blog_list'),
]
The problem now is BlogList is not being rendered anymore, but we don't need BlogList anymore - we can create a queryset inside BlogDetail and provide the queryset as a context. To achieve that I added a queryset variable and a get_context_data method to BlogDetail:
class BlogDetail(generic.DetailView):
model = Blog
template_name = 'blog.html'
queryset = Blog.objects.filter()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['blog_list'] = self.queryset
return context
I am trying to implement basic search functionality with Django. Could use help with accessing query inputs from forms in templates in functional or class based views. Intended functionality:
If exact search query page exists, display that page
If there is a page title that contains what was queried, show results of all
If neither, display a message stating no results found
I'm just learning, so I tried functional views and class based views. I've spent a really long time on documentation/videos/textbooks and don't see how to get the intended behavior out of class-based view. I understand collecting object_list and getting query_set, but how do you then route to those three different conditions. I tried overriding dispatch() and as_views() method to no avail. Tried with a Django form class and without.
For some reason, the functional view keeps executing the first try statement instead of throwing a DoesNotExist exception when the exact match isn't found. So it shows the entry page instead of the search results page. It seems like the request.GET is None type no matter what, as when I try to print nothing shows up.
urls.py
from re import search
from django.urls import path
from . import views
from .views import IndexPageView, SearchView
app_name = "wiki"
urlpatterns = [
# ex: /wiki/
path("", views.index, name="index"),
# path("", IndexPageView.as_view(), name="index"),
# ex: /wiki/EntryPageName
path("wiki/<str:entry>/", views.displayEntry, name="displayEntry"),
# path("wiki/search/", views.searchView, name="searchView")
path("wiki/search/", SearchView.as_view(), name="searchView")
]
model
class Entry(models.Model):
title = models.CharField(max_length=64)
def __str__(self):
return f"{self.title}"
content = models.TextField()
views.py
def searchView(request):
searchedTerm = request.GET.get('q')
try:
exactMatch = Entry.objects.get(title=searchedTerm)
entryTitle = exactMatch.title
entryHTML = markdown2.markdown(exactMatch.content)
return render(request, "encyclopedia/displayEntry.html", {
"entryTitle": entryTitle,
"entryHTML": entryHTML
})
except:
try:
searchResults = Entry.objects.filter(Q(title__icontains=searchedTerm))
return render(request, "encyclopedia/searchResults.html", {
"searchResults": searchResults,
"searchedTerm": searchedTerm
})
except:
return render(request, "encyclopedia/searchResults.html", {
"emptyResults": f"No entries found matching: {searchedTerm}",
"searchedTerm": searchedTerm
})
class SearchView(ListView):
template_name = "encyclopedia/searchResults.html"
model = Entry
context_object_name = "searchList"
def get_queryset(self):
searchedTerm = self.request.GET.get('q')
try:
searchResults = Entry.objects.get(title=searchedTerm)
return searchResults
except:
try:
searchResults = Entry.objects.filter(Q(title__icontains=searchedTerm))
return searchResults
except:
pass
def as_view():
searchedTerm = self.request.GET.get('q')
try:
exactMatch = Entry.objects.get(title=searchedTerm)
entryTitle = exactMatch.title
entryHTML = markdown2.markdown(exactMatch.content)
return render(request, "encyclopedia/displayEntry.html", {
"entryTitle": entryTitle,
"entryHTML": entryHTML,
})
except:
searchResults = Entry.objects.filter(Q(title__icontains=searchedTerm))
return render(request, "encyclopedia/searchResults.html", {
"searchResults": searchResults,
"searchedTerm": searchedTerm
})
else:
return render(request, "encyclopedia/searchResults.html", {
"emptyResults": f"No entries found matching: {searchedTerm}",
"searchedTerm": searchedTerm
})
search form from layout.html
<form action="{% url 'wiki:search' %}" method="GET">
<input class="search" type="text" name="q" placeholder="Search Encyclopedia">
<!-- <input type="submit" value="submit"> -->
</form>
display entry page template
{% extends "encyclopedia/layout.html" %}
{% block title %}
{% if entryTitle %}
{{ entryTitle }}
{% else %}
Page Not Found!
{% endif %}
{% endblock %}
{% block body %}
{% if entryHTML %}
{{ entryHTML|safe }}
{% else %}
<p>This page does not exist yet.</p>
<p>Check your spelling or create a new entry!</p>
<p>?? {{ testPrint }}</p>
{% endif %}
{% endblock %}
search results page
{% extends "encyclopedia/layout.html" %}
{% block title %}
Search Results: {{ searchedTerm }}
{% endblock %}
{% block body %}
{% if searchResults %}
<h3>Search Results</h3>
<ul>
{% for result in searchResults %}
<li>{{ result.title }}</li>
{% endfor %}
</ul>
{% else %}
<h3>{{ emptyResults }}</h3>
{% endif %}
{% endblock %}
Models
class Entry(models.Model):
title = models.CharField(max_length=64)
content = models.TextField()
def __str__(self):
return self.title
Views
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from app.models import Entry
class EntryListView(ListView):
model = Entry
paginate_by = 100 # if pagination is desired
def get_queryset(self):
queryset = super().get_queryset()
q = self.request.GET.get("q")
if q:
queryset = queryset.filter(title__icontains=q)
return queryset
class EntryDetailView(DetailView):
model = Entry
Urls
from django.urls import path
from app.views import EntryListView, EntryDetailView
urlpatterns = [
path('', EntryListView.as_view(), name='entry-list'),
path('<int:pk>/', ArticleDetailView.as_view(), name='entry-detail'),
]
using Django 1.9
How to extract all objects from class table that linked with another class table by foreign key.
I mean not all objects from one id but i mean all objects from all ids in one page. when i'm trying it gives me just one result
For instance:
urls.py
from django.conf.urls import url
from . import views
app_name = 'music'
urlpatterns = [
# /music/
url(r"^$", views.HomeView.as_view(), name='home'),
# /music/123/
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='details'),
# /music/song/
url(r'^song/$', views.songView, name='songs'),
]
views.py
from django.views import generic
from .models import Album, Song
from django.shortcuts import render
class HomeView(generic.ListView):
template_name = 'music/index.html'
def get_queryset(self):
return Album.objects.all()
class DetailView(generic.DetailView):
model = Album
template_name = 'music/details.html'
# Get all songs from all album (extracting songs from all of the albums in one page)
def songView(request):
for albums in Album.objects.all():
all_album = Album.objects.get(id=albums.id)
all_song = all_album.song_set.all()
return render(request, 'music/song.html', {'all_song': all_song})
songs.html
{% extends 'music/base.html' %}
{% block body %}
{% for song in all_song %}
<h2>{{ song }}</h2>
{% endfor %}
{% endblock %}
Another simple way to get the values in template is:
def songView(request):
album = Album.objects.all()
return render(request, 'music/song.html', {'album': album})
and in your templates you can iterate this way
{% for item in album %}
<h2>{{ item.title }}</h2>
{% for song in item.song_set.all %}
<h2>{{ song.title }}</h2>
{% endfor %}
{% endfor %}
You're just iterating through the Album objects and on every interaction rewrite the all_song variable without storing it somewhere. The proper way would be:
def songView(request):
songs = []
for album in Album.objects.all():
songs_per_album = album.song_set.all()
songs.append(song_per_album)
return render(request, 'music/song.html', {'all_song': songs})
Also, take a look at serializers it can be useful when serializing nested structures.
I don't understand why you doing this?
def songView(request):
for albums in Album.objects.all():
all_album = Album.objects.get(id=albums.id)
all_song = all_album.song_set.all()
return render(request, 'music/song.html', {'all_song': all_song})
You get all albums and than again make request to db to get album, and you just get all songs of specific album, if you want to get all songs just get all of them
songs = Song.objects.all()
if you want to get songs where album fk not null you can do like this:
album_ids = list(Album.objest.values_list('id', flat=True))
songs = Song.objects.filter(album_id__in=album_ids)
or
songs = Song.objects.filter(album_isnull=False)
I am following this tutorials and created a model and can see the data from admin page.
https://djangoforbeginners.com/message-board/
However, i am unable to see the see the posts in the html page. My html pages is inside the template:
Model:
pages/models.py
from django.db import models
# Create your models here.
class Post(models.Model):
text = models.TextField()
def __str__(self):
return self.text[:50]
View:
pages/views.py
class DiagramsPageView(TemplateView):
posts = Post.objects.all()
template_name = 'diagrams.html'
contex= {'posts': posts}
pages/urls.py
from .views import DiagramsPageView,
urlpatterns = [
path('diagrams/', DiagramsPageView.as_view(), name='diagrams'),
]
The HTML template page is here
<!-- templates/home.html -->
{% extends 'base.html' %}
{% block content %}
<h1>Diagrams</h1>
<h2>Styling Tables</h2>
<ul>
{{posts}}
</ul>
{% endblock content %}
The HTML page only outputting
Diagrams
Styling Tables
The variables you declare posts = Post.objects.all() and contex= {'posts': posts} are not automatically passed to the context, you have to use get_context_data
class DiagramsPageView(TemplateView):
template_name = 'diagrams.html'
def get_context_data(self, **kwargs):
context = super(DiagramsPageView, self).get_context_data(**kwargs)
context['posts'] = Post.objects.all()
return context
Note: You have to iterate through the object
And your html:
{% block content %}
<h1>Diagrams</h1>
<h2>Styling Tables</h2>
<ul>
{% for post in posts %}
{{ post }}
{% endfor %}
</ul>
Or use ListView
class DiagramsPageView(ListView):
model = Post
template_name = 'diagrams.html'
And your html:
{% block content %}
<h1>Diagrams</h1>
<h2>Styling Tables</h2>
<ul>
{% for post in object_list %}
{{ post }}
{% endfor %}
</ul>
{% endblock content %}
I'm creating a website which has two list views and a details view. I have no problem getting from the first listview to the second, but I'm unsure of how to make the url for the details view
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.ItemsView.as_view(), name='items'),
url(r'^(?P<category_id>[0-9]+)/(?P<products_id>[0-9]+)/$', views.DetailView.as_view(), name='details'),
]
im not sure what to replace "category_id" and "products_id" with on the bottom url
from django.http import Http404
from django.shortcuts import render
from django.views import generic
from .models import Category, Products
class IndexView(generic.ListView):
template_name = 'products/index.html'
context_object_name = 'all_categories'
def get_queryset(self):
return Category.objects.all()
class ItemsView(generic.ListView):
template_name = 'products/items.html'
context_object_name = 'all_items'
def get_queryset(self):
return Products.objects.all()
class DetailView(generic.DetailView):
model = Products
template_name = 'products/details.html'
html:
{% extends 'products/base.html' %}
{%block title%}Home{%endblock%}
{% block body %}
{% if all_items %}
<ul>
{% for product in all_items %}
<li>{{product.name}} </li>
{% endfor %}
</ul>
{% else %}
<h3>You have no categories</h3>
{% endif %}
{% endblock %}
also what would go in the url here where the question marks are
thanks
Use name of your url, define in your url.py.
Check the documentation
<li>{{ product.name }}</li>
Why do you need category in your url ?? You can access to your product like this. And your DetailView need only the primary key of the object.
url(r'^product/(?P<products_id>[0-9]+)/$', views.DetailView.as_view(), name='details'),