Query on generic display views - Django - django

For the below url routing for blog app,
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView
from blog.models import Post
urlpatterns=[
url(r'^$', ListView.as_view(
queryset=Post.objects.all().order_by("-date")[:25],
template_name="blog/blog.html",
)
)
]
template blog.html is,
{% extends "personal/header.html" %}
{% block content %}
{% for post in object_list %}
<h5>{{post.date|date:"Y-m-d"}} {{post.title}} </h5>
{% endfor %}
{% endblock %}
where model for blog app is defined as,
class Post(models.Model):
title = models.CharField(max_length=140)
body = models.TextField()
date = models.DateTimeField()
def __str__(self):
return self.title
MTV of blog app is structures as,
../blog
admin.py
apps.py
__init__.py
migrations
models.py
templates
tests.py
urls.py
views.p
Question:
{{post.id}} is internally created as primary key, for every row in the table, but,
What does /blog/{{post.id}} mean in the template(blog.html)?

When you want to go to a particular blog, you need to have a link to that. That's what /blog/{{post.id}} does as a link.
so /blog/1 gives you the first blog. Only that you have to define the url pattern, the view and the template for that.
url(r'^(?P<id>[^/]+)/$', views.get_blog, name='one_blog'),
Then in views:
def get_blog(request, id):
blog = Blogs.objects.get(id=id)
return render(request, 'blogs/one_blog.html', locals())
And then in templates folder, create a 'blogs/one_blog.html' file. Simplest example being:
{% extends "personal/header.html" %}
{% block content %}
<h5>{{blog.title}}</h5>
{{blog.body}}
{% endblock %}
Just make sure that you understand the folder structure for templates.

it's just a prefix /prefix/id/. It is also possible /article/1... it doesn't matter
urls.py
urlPatterns=[
url(r'^$', ListView.as_view(
model=Post,
template_name="blog/blog_list.html",
)
)
url(r'blog/(?P<pk>[\w-]+)/$', DetailView.as_view(
model=Post,
template_name="blog/blog_detail.html",
)
)
]

Related

Django Filter Queryset Model

How can I filter my table to only show the quotes from a project.
In order to display all quotes, I am using {% for quote in quotes.all %}
Now, I would like to display quote relative to a site. Which means when selecting my site_id, I`ll be able to only see the quote relative to this site_id. I could write something like
{% for quote in quotes.all %}
{% if quote chantier.id %}
{% endif %}
{% endfor %}
but this is wrong.
Here is my model for quote:
models.py
class Quote(models.Model):
name = models.CharField(max_length=30)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
How can I display all quotes from this site?
Many Thanks,
You can make a url path that contains the site_id:
# app_name/urls.py
from django.urls import path
from app_name import views
urlpatterns = [
path('site/<int:site_id>/', views.quotes_of_site, name='quotes_of_site'),
# …
]
in the view, you can then filter by site_id:
# app_name/views.py
from django.shortcuts import render
from app_name.models import Quote
def quotes_of_site(request, site_id):
quotes = Quote.objects.filter(site_id=site_id)
return render(request, 'name_of_template.html', {'quotes': quotes})
and then iterate over this QuerySet:
{% for quote in quotes %}
…
{% endfor %}

django template internal url concatenation

In my django project, I have URL patterns like below.
urls.py in project root:
urlpatterns = [
path('', include('blog.urls')),
]
urls.py in app(blog) root:
urlpatterns = [
path('', views.index, name='index'),
path(
'category/<str:category_id>',
views.category_view,
name='category_view',
),
]
What I want to do is making hyperlink for each category with django template. Something like below.
{% for category in categories %} .
<a href="{{ {% url 'index' %}|add: {% url 'category_view' category %} }} " class="nav">
{{category}}
</a>
{% endfor %}
However, it doesn't work. There are too many categories that I can't hard code any of them, but have to make url "(domain root)/category/(category name)" with django template. How can I concatinate two url in a template (as django does with
path(A, include(B))
)
You can define a get_absolute_url method in your Category model, it is a much cleaner solution: https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url
Implementation example:
from django.urls import reverse_lazy
# for django < 1.10 from django.core.urlresolvers import reverse_lazy
class Category(models.Model):
...
def get_absolute_url(self):
return reverse_lazy('category_view', category_id=self.id)
and in your template:
{% for category in categories %} .
<a href="{{ category.get_absolute_url }}" class="nav">
{{category}}
</a>
{% endfor %}

Django 2.0: Get queries dynamically from search

I am new to Django framework and as a practice project I am trying to build an ecommerce website using Django. I have a class based view for my search page. I wrote the view to get the query for a particular query:
views.py
class SearchProductView(ListView):
template_name = "template.html"
queryset = Product.objects.filter(title__icontains='book')
print(queryset)
I would like to know how I can write a function to get the search queries dynamically. For e.g.: If i search book, then my queryset should contain all things about book and if I search car, then I should get all things about car.
template.html
{% extends "base.html" %}
{% block content %}
<div class='row'>
{% for object in object_list %}
<div class='col'>
{{ forloop.counter }}
{% include 'products/snippets/card.html' with instance=object %}
</div>
{% endfor %}
</div>
{% endblock %}
urls.py
from django.urls import path
from . import views
from .views import SearchProductView
app_name = 'search'
urlpatterns = [
path('', SearchProductView.as_view(), name='search_page'),
]
You need to define the get_queryset method, rather than the class-level queryset attribute. This can use your querystring parameters to filter the queryset dynamically.
You haven't shown your search form or said what your parameter is, but assuming it submits a GET parameter named q, you would do:
def get_queryset(self):
return Product.objects.filter(title__icontains=self.request.GET['q'])
Although the answer above will work I believe a better solution would be the following:
models.py
class Category(models.Model):
title = models.CharField(...)
class Product(models.Model):
...
category = models.ForeignKey(Category)
views.py
from django.db.models import Q
def get_queryset(self):
querystr = self.request.GET['q']
Product.objects.filter(
Q(title__icontains=querystr) | Q(category__title__icontains=querystr)
)

ListView for Django not Working but function based view is working

When I am using function based view using the following code:
from django.views import View
from django.views.generic import TemplateView, ListView
from .models import Restaurant
def restaurant_listview(request):
template = 'restaurants/restaurants_list.html'
context = {
"queryset" : Restaurant.objects.order_by('-updated')
}
return render (request, template, context)
it is working with the url file kept as follows:
from django.conf.urls import url
from django.contrib import admin
from restaurants import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^restaurants/$', views.restaurant_listview),
]
But when I am trying to do the same thing with class based views it is not working only the following portion doesn't seem to work:
<ul>
{% for obj in queryset %}
<li>{{obj.name}}, {{obj.location}}, {{obj.category}}, {{obj.timestamp}}</li>
{% endfor %}
</ul>
the following part works fine:
{% extends 'base.html' %}
{% block title %}
Restaurants List {{ block.super }}
{% endblock %}
{% block content %}
<h1>Restaurants</h1>
for class based view my views.py is:
class RestaurantListView(ListView):
queryset = Restaurant.objects.all()
template_name = 'restaurants/restaurants_list.html'
and urls.py is:
url(r'^restaurants$', RestaurantListView.as_view(), name='Home')
P.S. I am following this guide : https://www.youtube.com/watch?v=yDv5FIAeyoY&t=25471s
For a list view, you should change the template to:
{% for obj in restaurant_list %}
Or, if you really want to use the variable queryset in the template, then set context_object_name.
class RestaurantListView(ListView):
queryset = Restaurant.objects.all()
template_name = 'restaurants/restaurants_list.html'
context_object_name = 'queryset'

Django Tutorial Page not found 404 [duplicate]

I was following the django documentation and making a simple poll app. I have come across the following error :
Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:
^polls/
^admin/
The current URL, , didn't match any of these."
settings.py
ROOT_URLCONF = 'mysite.urls'
mysite/mysite/urls.py
from django.conf.urls import include,url
from django.contrib import admin
urlpatterns = [
url(r'^polls/',include('polls.urls')),
url(r'^admin/', admin.site.urls),]
mysite/polls/urls.py
from django.conf.urls import url
from . import views
app_name= 'polls'
urlpatterns=[
url(r'^$',views.IndexView.as_view(),name='index'),
url(r'^(?P<pk>[0-9]+)/$',views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>[0-9]+)/results/$',views.ResultsView.as_view(),name='results'),
url(r'^(?P<question_id>[0-9]+)/vote/$',views.vote,name='vote'),]
mysite/polls/views.py
from django.shortcuts import get_object_or_404,render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.views import generic
from django.utils import timezone
from django.template import loader
from .models import Choice,Question
from django.template.loader import get_template
#def index(request):
# return HttpResponse("Hello, world. You're at the polls index")
class IndexView(generic.ListView):
template_name='polls/index.html'
context_object_name='latest_question_list'
def get_queryset(self):
"""Return the last five published questions."""
return Question.objects.filter(pub_date__lte=timezone.now()).order_by('-pub_date')[5:]
class DetailView(generic.DetailView):
model=Question
template_name='polls/detail.html'
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
return Question.objects.filter(pub_date__lte=timezone.now())
class ResultsView(generic.DetailView):
model= Question
template_name ='polls/results.html'
def vote(request, question_id):
question=get_object_or_404(Question, pk=question_id)
try:
selected_choice= question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/details.html',
{
'question':question,
'error_message' : "You didn't select a choice" ,
})
else:
selected_choice.votes+=1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
index.html
<!DOCTYPE HTML >
{% load staticfiles %}
<html>
<body>
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="{% url 'polls:detail' question.id %}">{{question.question_test }}
</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
</body>
</html>
This link http://127.0.0.1:8000/polls/ shows a blank page with 3 bullets. (I have 3 questions in my database and their id's are 5,6,7 because I have been deleting and adding the questions.)
My admin works fine!
I'm new to Django and have been searching and asking around and have been stuck on it for a while now.
You get the 404 on http://127.0.0.1:8000/ because you have not created any URL patterns for that url. You have included the url http://127.0.0.1:8000/polls/, because you have included the polls urls with
url(r'^polls/',include('polls.urls')),
The empty bullets suggest that there is a problem with your polls/index.html template. It looks like you have a typo and have put {{ question.question_test }} instead of {{ question.question_text }}. Make sure that it exactly matches the template from the tutorial 3:
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>{{ question.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
Make sure there is no typo in your code. Putting space between inverted commas can also lead to this error. Just make sure you have put path('',include('home.urls')) and not path(' ',include('home.urls'))
Note: here home.urls is the name of my app in Django