I am new on django and got a problem.
I got 2 apps, one is slider which i get slider images and other one is products.
I've featured product option in my product model which i want to show on index page.
This is my views.py
def index(request):
allslides = SliderImage.objects.all()
context = {
'allslides': allslides
}
return render(request, 'pages/index.html', context)
def fproducts(request):
fproducts = Product.objects.filter(is_featured=True)
context = {
'fproducts': fproducts
}
return render(request, 'pages/index.html', context)
I've made some research and it looks django doesn't allow 2 views in one page.
That's my index.html
<div id="homepageslider" class="flexslider">
<ul class="slides">
{% for s in allslides %}
<li class=""><img src="{{ s.image.url }}" title="{{ s.alt }}"></li>
{% endfor %}
</ul>
</div>
<div class="container">
{% if fproducts %}
{% for product in fproducts %}
<div class="col-md-4 col-lg-3 col-sm-6 col-12 mb-4 px-1">
<div class="card">
<img src="{{ product.main_image.url }}" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title text-truncate">{{ product.title }}</h5>
<p class="card-text">{{ product.kod }}</p>
</div>
</div>
</div>
{% endfor %}
{% else %}
<p>No Products</p>
{% endif %}
Thanks for help.
Do it in one view:
def index(request):
allslides = SliderImage.objects.all()
fproducts = Product.objects.filter(is_featured=True)
context = {
'allslides': allslides,
'fproducts': fproducts,
}
return render(request, 'pages/index.html', context)
Related
I am currently facing this problem with Django ListView. Basically, I need to filter some questions per topic and I would like to paginate the results.
My code is working perfectly about the queryset part (the results are showed correctly) but I am facing a problem with pagination.
Let's say I have so far 8 items in my query, if I choose to paginate_by = 10, it shows me just one page. If, otherwise, I choose to paginate by, let's say, 3, it shows me 3 pages to choose in the template (which is correct) but it shows me ALL the results of the query in my page.
I post some code to be more clear
models.py:
class Tag(models.Model):
name = models.CharField(max_length=300, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def clean(self):
self.name = self.name.capitalize()
def __str__(self):
return self.name
class Question(models.Model):
post_owner = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=5000, default='')
body = tinymce_models.HTMLField()
tags = models.ManyToManyField(
Tag, related_name='tags')
viewers = models.ManyToManyField(
User, related_name='viewed_posts', blank=True)
views.py:
class TagQuestionsListView(ListView):
template_name = 'main/tag_questions.html'
paginate_by = 20
def get_queryset(self, **kwargs):
tag = Tag.objects.get(name=self.kwargs['name'])
questions = Question.objects.filter(tags=tag)
return questions
def get_contextdata(self, **kwargs):
context = super().get_context_data(**kwargs)
context['tag'] = Tag.objects.get(name=self.kwargs['name'])
context['questions'] = Question.objects.filter(
tags=context['tag'], is_deleted=False)
return context
template:
{% extends 'base.html' %}
{% load humanize %}
{% block title %}Domande su {{tag.name}}{% endblock title %}
{% block content %}
<style>
.text {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2; /* number of lines to show */
line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>
<div class="card">
<div class="mt-3">
<h3 class="ms-2" style="display: inline;">Ultime {{ questions.count }} Domande</h3>
{% if request.user.is_authenticated %}
Fai una domanda
{% else %}
Fai una domanda
{% endif %}
</div>
<h5 class="ms-2">{{ total_questions.count }} domande totali </h5>
<hr>
{% for question in questions %}
<div class="row">
<div class="col-2 ms-2">
<p>{{ question.count_all_the_votes }} Voti</p>
<p>{{ question.count_answers }} Risposte</p>
<p>{{ question.calculate_viewers }} Visualizzazioni</p>
</div>
<div class="col-9">
<h5>{{question.title}}</h5>
<div class="text">
{{ question.body|striptags }}
</div>
{% for tag in question.tags.all %}
<a class="btn btn-sm btn-outline-primary m-1" href="{% url 'main:tag_questions' name=tag.name %}">{{tag.name}}</a>
{% endfor %}
<div class="float-end">
<a style="display: inline;" href="">{{question.post_owner}}</a>
{% if question.is_edited == False %}
<span style="display:inline;">creata {{question.created_at | naturaltime}}</span>
{% else %}
<span style="display:inline;"> modificata {{question.edited_time | naturaltime}} da <a style="display: inline;" href="">{{question.edited_by.username}}</a></span>
{% endif %}
</div>
</div>
</div>
<hr>
{% endfor %}
</div>
<div class="row mt-3">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<nav aria-label="Page navigation example">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item"><a class="page-link" href="{% url 'main:tag_questions' name=tag.name %}?filter={{ filter }}&orderby={{ orderby }}&page={{ page_obj.previous_page_number }}">Precedente</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">Precedente</a></li>
{% endif %}
{% for i in paginator.page_range %}
<li class="page-item {% if page_obj.number == i%} active {% endif %} %} "><a class="page-link" href="?filter={{ filter }}&orderby={{ orderby }}&page={{ i }}">{{i}}</a></li>
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item"><a class="page-link" href="{% url 'main:tag_questions' name=tag.name %}?filter={{ filter }}&orderby={{ orderby }}&page={{ page_obj.next_page_number }}">Prossima</a></li>
{% else %}
<li class="page-item disabled"><a class="page-link" href="#">Prossima</a></li>
{% endif %}
</ul>
</nav>
</div>
</div>
</div>
{% endblock content %}
With this I want my comment converter to answer.
You have to use page_obj instead questions in your template.
<--! ⬇️⬇️⬇️ -->
{% for question in page_obj %}
<div class="row">
<div class="col-2 ms-2">
<p>{{ question.count_all_the_votes }} Voti</p>
<p>{{ question.count_answers }} Risposte</p>
<p>{{ question.calculate_viewers }} Visualizzazioni</p>
</div>
<div class="col-9">
<h5>{{question.title}}</h5>
<div class="text">
{{ question.body|striptags }}
</div>
{% for tag in question.tags.all %}
<a class="btn btn-sm btn-outline-primary m-1" href="{% url 'main:tag_questions' name=tag.name %}">{{tag.name}}</a>
{% endfor %}
<div class="float-end">
<a style="display: inline;" href="">{{question.post_owner}}</a>
{% if question.is_edited == False %}
<span style="display:inline;">creata {{question.created_at | naturaltime}}</span>
{% else %}
<span style="display:inline;"> modificata {{question.edited_time | naturaltime}} da <a style="display: inline;" href="">{{question.edited_by.username}}</a></span>
{% endif %}
</div>
</div>
</div>
<hr>
{% endfor %}
So, if you define attribute paginate_by , than ListView(django docs) adds a paginator and page_obj to the context. To allow the users to navigate between pages, add links to the next and previous page, in your template.
I'm currently working on an e-commerce site and I'm trying to create a product list page that spans into another page after 4 items have been displayed. rendering the page doesn't produce any error but all items in the database are displayed on the same page and remains the same even after switching to another page.
Here's my views.py:
from django.shortcuts import render, get_object_or_404
from .models import Category, Item
from django.core.paginator import Paginator
def item_list(request, category_slug=None):
category = None
categories = Category.objects.all()
items = Item.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
items = items.filter(category=category)
paginator = Paginator(items, 4)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request,
'item/list.html',
{'category': category,
'categories': categories,
'page_obj': page_obj,
'items': items})
my urls.py file:
from django.urls import path
from . import views
app_name = 'shop'
urlpatterns = [
path('', views.item_list, name='item_list'),
path('<slug:category_slug>/', views.item_list, name='item_list'),
path('<int:id>/<slug:slug>/', views.item_detail, name='item_detail'),
]
pagination snippet from the template
<nav class="d-flex justify-content-center wow fadeIn">
<ul class="pagination pg-blue">
<!--Arrow left-->
{% if page_obj.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
Next
{% endif %}
</ul>
</nav>
and the logic that displays the products
<div class="row wow fadeIn">
<!--Grid column-->
{% for item in items %}
<div class="col-lg-3 col-md-6 mb-4">
<!--Card-->
<div class="card" style="width: 16rem; height: 25rem">
<!--Card image-->
<div class="view overlay">
<a href="{{ item.get_absolute_url }}">
{% if item.tags and item.label %}
<div class="imgHolder">
<img src="{{ item.image.url }}" class="img-fluid">
<span class="badge badge-pill {{ item.get_label_display }}-color">{{ item.tags }}</span>
</div>
{% else %}
<img src="{{ item.image.url }}" class="img-fluid">
{% endif %}
</a>
<a href="{{ item.get_absolute_url }}">
<div class="mask rgba-white-slight"></div>
</a>
</div>
<!--Card image-->
<!--Card content-->
<div class="card-body text-center" style="height: 9rem;">
<!--Category & Title-->
<a href="{{ item.category.get_absolute_url }}" class="grey-text">
<h5>{{ item.category.name|truncatechars:20 }}</h5>
</a>
<h5>
<strong style="color:red">
{{ item.name }}
</strong>
</h5>
<h6 class="font-weight-bold">
{% if item.discount_price %}
<strong><del>${{ item.price}}</del></strong>
<strong>${{ item.discount_price }}</strong>
{% else %}
<strong>${{ item.price }}</strong>
{% endif %}
</h6>
</div>
<!--Card content-->
</div>
<!--Card-->
</div>
{% endfor %}
</div>
I'd really like to know what I'm doing wrong and I'm also open to alternative means of solving the same problem. Thanks
You are using all the queryset that you are passing to the paginator. You must iterate over the page_obj.object_list.
page_obj = paginator.get_page(page_number)
page_obj_items = page_obj.object_list
you need to loop throw {% for item in page_obj %}
I am currently working on a django blog and I've coded a search bar where you type something and, if there's any post that contains what you've typed in the title, it should appear all the posts. This part is perfectly well-written. However, there's an error with the pagination. As you'll see in the views.py. The maximum num of posts per page is 3. However, you can see there's four. However, the paginator detects there should be another page for the fourth posts. Here's an image that shows that.
Here's the views.py:
class ElementSearchView(View):
elements_list = Element.objects.all()
def get(self, request, *args, **kwargs):
paginator = Paginator(self.elements_list, 3)
page_request_var = 'page'
page = request.GET.get(page_request_var)
try:
paginated_queryset = paginator.page(page)
except PageNotAnInteger:
paginated_queryset = paginator.page(1)
except EmptyPage:
paginated_queryset = paginator.page(paginator.num_pages)
queryset = Element.objects.all()
query = request.GET.get('q')
if query:
queryset = queryset.filter(
Q(title__icontains=query)
).distinct()
context = {
'query': queryset,
'queryset': paginated_queryset,
'page_request_var': page_request_var,
}
return render(request, 'periodic/search_results_table.html', context)
And here's the html template: The pagination is at the end of the template.
{% load static %}
<html>
{% include 'periodic/head_search.html' %}
<body>
{% include 'periodic/header.html' %}
<br>
<br>
<div class="container">
<div class="row">
<!-- Latest Posts -->
<main class="posts-listing col-lg-8">
<div class="container">
<div class="row">
<!-- post -->
{% for element in query %}
<div class="post col-xl-6 wrap-login100">
<div class="post-thumbnail"><img src="{{ element.thumbnail.url }}" alt="..." class="img-fluid"></div>
<div class="post-details">
<a href="{{ element.get_absolute_url }}">
<h3 class="h4">{{ element.title }}</h3></a>
</div>
</div>
{% endfor %}
</div>
<!-- Pagination -->
<nav aria-label="Page navigation example">
<ul class="pagination pagination-template d-flex justify-content-center">
{% if queryset.has_previous %}
<li class="page-item"> <i class="fa fa-angle-left"></i></li>
{% endif %}
<li class="page-item">{{ queryset.number }}</li>
{% if queryset.has_next %}
<li class="page-item"> <i class="fa fa-angle-right"></i></li>
{% endif %}
</ul>
</nav>
{% if is_paginated %}
<nav aria-label="Page navigation example">
<ul class="pagination pagination-template d-flex justify-content-center">
{% if page_obj.has_previous %}
<li class="page-item"> <i class="fa fa-angle-left"></i></li>
{% endif %}
<li class="page-item">{{ page_obj.number }}</li>
{% if page_obj.has_next %}
<li class="page-item"> <i class="fa fa-angle-right"></i></li>
{% endif %}
</ul>
</nav>
{% endif %}
</div>
</main>
</body>
{% include 'periodic/scripts_search.html' %}
</html>
As the user #ikilnac mentioned,
you are looping over the original queryset and not the paged one in your template
That simply means that in your loop, you do this
{% for element in query %}
<div class="post col-xl-6 wrap-login100">
<div class="post-thumbnail"><img src="{{ element.thumbnail.url }}" alt="..." class="img-fluid"></div>
<div class="post-details">
<a href="{{ element.get_absolute_url }}">
<h3 class="h4">{{ element.title }}</h3></a>
</div>
</div>
{% endfor %}
And then after that, you are using the tag in the form of {% if queryset.has_previous %} with the original queryset rather than the paged one in the template (the query).
There's a good example of it here - Paginate with Django
I want to show all the user's Items.
Currently I can only show 1 object
my_items.html (where i want it to show)
{% extends 'base.html' %}
{% block content%}
<main role="main">
<div class="container">
<!-- Example row of columns -->
<div class="row">
{% for item in item %}
<!--{% if item.id == request.user.id %}-->
<div class="col-md-4">
<div class="col-md-4">
<img style="max-width: 100px; max-height: 300px" src="{{ item.thumb.url }}">
</div>
<h2>{{ item.name }}</h2>
<p>{{ item.snippet }}</p>
<p>{{ item.date }}</p>
<p><a class="btn btn-warning" href="#" role="button">Edit</button></a></p>
<p><a class="btn btn-danger" href="#" role="button">Delete</a></p>
</div>
<!--{% endif %}-->
{% endfor %}
</div>
<hr>
</div> <!-- /container -->
</main>
{% endblock %}
views.py
def item_myitems(request):
item = Item.objects.all().order_by('date')
return render(request, 'items/my_items.html', {'item': item})
I tried using filter() and get() on views.py
You should use a plural name to pass your items to your view:
def item_myitems(request):
items = Item.objects.all().order_by('date')
return render(request, 'items/my_items.html', {'items': items})
So you can distinguish one item from many items when you loop through them in your view:
{% for item in items %}
omg I got it working, i feel so dumb right now LOL
I uncommented my if in the html and set to this > {% if item.author_id == request.user.id %} i was comparing with the item id instead of the author_id
Im facing implementing the dynamic testimonials and carousel in django python, means i need to content in models that so present in front below i mention my code of implemetions
template.html
<div id="myCarousel" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel" data-slide-to="1"></li>
<li data-target="#myCarousel" data-slide-to="2"></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner">
{% for p in tests %}
{% if forloop.counter == 1 %}
<div class="item active">
{% else %}
<div class="item">
{% endif %}
<h3>{{ p.title }}</h3>
</div>`enter code here`
</div>
{% endfor %}
</div>
</div>
view.py
def home(request):
test=Testimonials.objects.all().order_by('id')[:13]
template = loader.get_template('hme/home.html')
context = {
'tests':test,
}
return HttpResponse(template.render(context, request))
I don't know what you really want to do, but your views.py can be rewrite as follows:
from django.shortcuts import render
def home(request):
tests = Testimonials.objects.order_by('id')[:13]
return render(request, 'hme/home.html', {'tests': tests})