how to display model data to html page - django

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 %}

Related

How to add Wagtail blog categories as links in header and footer

I am building simple blog with posts and posts categories.
I would like to add links to posts categories to header and footer, so they appear on every page, not just home page (as routable pages).
How do I go about it?
Category class as below:
class BlogCategory(models.Model):
title = models.CharField( # field name has to be 'title'
verbose_name='Name', max_length=30, unique=True)
slug = AutoSlugField( populate_from='title', editable=True)
panels = [
MultiFieldPanel([
FieldPanel("title"),
FieldPanel("slug"),
], heading="New Category"),]
def __str__(self):
return self.title
Code for routable page:
class BlogIndexPage(RoutablePageMixin, Page):
class Meta:
verbose_name = "Blog Index Page"
template = "blog/blog_index_page.html"
parent_page_types = ["wagtailcore.Page"]
subpage_types = ["blog.PostArticlePage"]
max_count = 1
# context ------------------------------
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
all_posts = (
BlogDetailPage.objects.live().public().order_by("-first_published_at")
)
context["posts"] = all_posts
#route(r"^category/(?P<cat_slug>[-\w]*)/$", name="category_view")
def category_view(self, request, cat_slug):
context = self.get_context(request)
try:
category = BlogCategory.objects.get(slug=cat_slug)
except Exception:
return redirect(self.url)
if category is None:
return redirect('/')
context["posts"] = (BlogDetailPage.objects.live().public().filter(categories__in=[category]))
return render(request, "blog/blog_view_page.html", context)
Try this from here :
{% regroup object_list by category as post_list %}
<ul>
{% for post_category in post_list %}
<li>{{ post_category.grouper }}
<ul>
{% for post in post_category.list %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
You may have to modify it a bit but the principal is the same.
The regroup tag is well explained in the Django docs and Wagtail docs clearly mention they support Django tags.
To add blog categories to header and footer:
First create a simple template tag
register = template.Library()
#register.simple_tag()
def get_categories():
return BlogCategory.objects.all()
Next add following code to header and footer
{% load blog_tags %}
{% get_categories as categories %}
<nav>
<ul>
{% for cat in categories %}
<li>{{ cat.title }}</li>
{% endfor %}
</ul>
</nav>
Finally, reload the server.

How to get a list of articles filtered by tag using django-taggit?

I want to list articles by tag to have the title of the tag in the title and the titles of the articles in the list.
My view.py looks like this:
from taggit.models import TaggedItem
class ArticlesByTagsList(ListView):
template_name = 'articles/articles_by_tags.html'
context_object_name = 'articles_list'
def get_queryset(self):
return TaggedItem.objects.filter(tag=self.kwargs['tag'])
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['tags_list'] = Tag.objects.all()
return context
My articles_by_tags.html template looks like this:
{% block content %}
<h1>Список публикаций {{ articles_list.item }}</h1>
{% for item in articles_list %}
<h2>{{ item }}</h2>
{% endfor %}
{% endblock %}
I end up with the following output:ArticlesByTagsList.as_view() result
How can I solve this problem?

can't use id and str:username together

I created a blog where you can go to the user's profile and see their posts. You can also see each post separately.
However, I cannot use such url path path ('<str: username> / <post_id> /', post_view, name = 'tak'). This results in Reverse for 'tak' with arguments '(44,)' not error found.
here is my code
views.py
def user_posts(request, username):
posts = Post.objects.filter(author__username=username)
return render(request, 'profile.html', {'posts':posts})
def post_view(request,post_id):
post = Post.objects.get(id=post_id)
context={'post':post}
return render(request, 'post.html',context)
urls.py
path('<str:username>/', user_posts, name='profile'),
path('<str:username>/<post_id>/', post_view, name='tak'),
models.py
class Post(models.Model):
text=models.CharField(max_length=25)
pub_date=models.DateTimeField('date published',auto_now_add=True)
author=models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
# Create your models here.
def __str__(self):
return self.text
profile.html
{% extends 'base.html' %}
{% block content %}
{% for post in posts %}
<ul><li>
{{post}}
<hr>
<p>
{{post}}</p>
</li>
</ul>
{% endfor %}
{% endblock content %}
Path tak expects two arguments, while you send only one: In your profile.html replace:
{{post}}</p>
With:
{{post}}</p>

Django Search Implementation, conditional routing

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'),
]

Django model.objects.all() queryset not displaying content - how to fix?

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"