django blog archive, index and pagination comprehensive application - python

Background:
I am building a blog about my research group. On the publication archive page I am going to display all the publications of my mentor. Here there is a side column to show the archive index allowing users to view the publications by year. And at the bottom of the page there is a django paginator which separate the publications in to several pages with 7 publications per page.
Problem:
When the pagination is used, the publications is divided into a list, so the {{publication.published_time}} only contain the data in the current page rather than the whole dataset. Thus, I wrote the hard code of year information in the front end and add the url to the corresponding year.
Apparently, I wish I can get the distinct year information about all publications on the basis of the existence of a paginator. Besides, transfer the year value directly in the URL.
Code:
url.py:
url(r'^publications/(?P<year>[0-9]{4})/$', PublicationYearArchiveView.as_view(),
name="publication_year_archive"),
views.py:
class PublicationYearArchiveView(YearArchiveView):
queryset = Publication.objects.all()
date_field = "published_time"
make_object_list = True
allow_future = True
def listing(request):
limit = 7
publication_list = Publication.objects.all().order_by('published_time').reverse()
paginator = Paginator(publication_list, limit) # Show 7 publications per page
page = request.GET.get('page')
try:
publications = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
publications = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
publications = paginator.page(paginator.num_pages)
return render(request,
'research_spacecoupe/research_accomplishment.html',
{'publications': publications})
research.html:
Paginator:
{% if publications.has_other_pages %}
<ul class="pagination">
{% if publications.has_previous %}
<li>«</li>
{% else %}
<li class="disabled"><span>«</span></li>
{% endif %}
{% for i in publications.paginator.page_range %}
{% if publications.number == i %}
<li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if publications.has_next %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
Index:
<div class="sidebar-module">
<h4>Archive</h4>
<ol class="list-unstyled">
<li>all publications</li>
<li>2017</li>
<li>2016</li>
<li>2015</li>
<li>2013</li>
<li>2012</li>
<li>2011</li>
<li>2010</li>
</ol>
</div>
Note:
Now the page does work, and I can click the year(eg. 2017) to view the publications published in 2017 and click the "All publications" to view all publications. But I want to replace the number of year with distinct publications.published_time of all publications. Anything I can do to fix it?

views.py:
from django.db.models.functions import ExtractYear
from django.db.models import Count
# ...
def listing(request):
# ...
years = Publication.objects \
.annotate(year=ExtractYear('published_time')) \
.values_list('year') \
.annotate(count=Count('id')) \
.values_list('year', flat=True) \
.order_by('year')
return render(request,
'research_spacecoupe/research_accomplishment.html',
{'publications': publications,
'years': years})
research_accomplishment.html:
<div class="sidebar-module">
<h4>Archive</h4>
<ol class="list-unstyled">
<li>all publications</li>
{% for year in years %}
<li>{{ year }}</li>
{% endfor %}
</ol>
</div>

Related

Search Bar in Django?

I have a bootstrap search bar and I want it to search for a list of all tags in a database. Tags are a like a facebook page or reddit tags.
When I submit my search, I want the URL to include the GET-parameter: ?q="typeword", but the application has to redirect to a new page, and preserve the tags parameter while doing so. How can I do this?
I have tried using GET-request and paginator, but nothing seems to work. I can add a new URL "search/" and then it works, but only with this url.
models.py
class Tag(models.Model):
path = models.CharField(max_length=37,default=0)
name = models.CharField(max_length=35)
description = models.CharField(max_length=200)
image = models.ImageField(default='default.jpg',upload_to='tag_pics')
def __str__(self):
return self.path
views.py
def search(request):
q = request.GET.get('q',None)
items=''
if q is None or q is "":
items = Tag.objects.all()
elif q is not None:
items = Tag.objects.filter(name__contains=q)
paginator = Paginator(items, 3)
page = request.GET.get('page')
items = paginator.get_page(page)
title = "Search"
return render(request, 'blog/search.html',{'items': items, 'title': title})
search.html
{% extends 'blog/base.html' %}
{% block content %}
{% if items %}
<p class="search-count">Found
<strong>
{{ items.paginator.count }}
</strong>
result{{ items.paginator.count|pluralize }}
</p>
{% for i in items %}
{{ i.path }}
{% endfor %}
{% elif request.GET.q %}
<p class="search-no-results">
No results for "<strong>{{ request.GET.q }}"
</p>
{% endif %}
{% endblock %}

Pagination in Django not working as expected

I wanted pagination for all the courses available and that was easy to achieve. But now I'm stuck because I wanted pagination for faculties also, which will show specific courses of the accessed faculty. I have 4 models: faculties, departments, studies, and courses. The pagination will show for faculties as well, but the problem is that if I try to go to the second page, it will redirect me to the second page of all courses list. Or, if I change page on all courses and then try to access a faculty, no course will show at all in the faculty.
def index(request):
course_list = Course.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(course_list, 1)
try:
courses = paginator.page(page)
except PageNotAnInteger:
courses = paginator.page(1)
except EmptyPage:
courses = paginator.page(paginator.num_pages)
faculty_list = Faculty.objects.all()
page = request.GET.get('page2', 1)
paginator = Paginator(faculty_list, 1)
try:
faculties = paginator.page(page)
except PageNotAnInteger:
faculties = paginator.page(1)
except EmptyPage:
faculties = paginator.page(paginator.num_pages)
context = {'courses': courses,
'faculties': faculties,
'departments': Department.objects.all(),
'studies': StudyProgramme.objects.all(),
'teachers': Teacher.objects.all()
}
return render(request, 'courses/index.html', context)
<div id="crs">
<h3>All courses</h3>
<ul>
{% for course in courses %}
<li><a href={{ course.slug }}>{{ course.name }}</a></li>
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if courses.has_previous %}
« first
{{ courses.previous_page_number }}
{% endif %}
<span class="current">
Page {{ courses.number }} of {{ courses.paginator.num_pages }}
</span>
{% if courses.has_next %}
{{ courses.next_page_number }}
last »
{% endif %}
</span>
</div>
</div>
{% for faculty in faculties %}
<div id="fac_{{ faculty.pk }}_tab" style="display:none;">
<h3> {{ faculty.name }} Courses</h3>
<ul>
{% for department in faculty.department_set.all %}
{% for study in studies %}
{% if study.department == department %}
{% for course in courses %}
{% if course.study_programme == study %}
<li>
<a class="first" href={{ course.slug }}>{{ course.name }}</a>
</li>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if faculties.has_previous %}
« first
{{ faculties.previous_page_number }}
{% endif %}
<span class="current">
Page {{ faculties.number }} of {{ faculties.paginator.num_pages }}
</span>
{% if faculties.has_next %}
{{ faculties.next_page_number }}
last »
{% endif %}
</span>
</div>
</div>
{% endfor %}
It's not a Django problem that your view is most certainly handle one pagination parameter page which will direct to courses, so if you changed the get parameter for each of your model pagination it will work.
ex:
## views.py
page = request.GET.get('page')
## yourtemplate.html
yourtext
localhost:8000/MYVIEW/?page=2 # Goes to courses
## views.py
page = request.GET.get('faculties')
## yourtemplate.html
yourtext
##
localhost:8000/MYVIEW/?faculties=2 # Goes to faculties
etc..
edited:
{% for faculty in faculties %} change it to {% for faculty in faculties2 %} and remove faculties from your context, cuz you are repeating yourself as faculties2 and faculties hold the same queryset .
paginator = Paginator(course_list, 1)
paginator = Paginator(faculty_list, 1)
Changing your second instance name to paginator_two would solve your problem

Django paginator page range for not displaying all numbers

I have a pagination in my site but it shows me every page like 1-19, i only want to display only 5 pages.
How can i do this?
views.py
paginator = Paginator(object_list, new_number_of_list)
page = request.GET.get('page')
try:
Items = paginator.page(page)
except PageNotAnInteger:
Items = paginator.page(1)
except EmptyPage:
Items = paginator.page(paginator.num_pages)
variables = RequestContext(request, {"Items": Items,
"ForItemCount": ForItemCount,
"page": page,
})
return render(request, 'templates/Core/resource_base.html',
variables)
my pagination.html
<div class="pagination p1">
<span class="step-links">
<ul>
{% for l in Items.paginator.page_range %}
<li>{{forloop.counter}}</li>
{% endfor %}
</ul>
</span>
</div>
Another quick solution that can be used(+ and - 5 limit for example):
{% for l in Items.paginator.page_range %}
{% if l <= Items.number|add:5 and l >= Items.number|add:-5 %}
<li>{{forloop.counter}}</li>
{% endif %}
{% endfor %}
You already have the {{ forloop.counter }} in there, you can use that to limit it to five.
{% for l in Items.paginator.page_range %}
{% if forloop.counter < 5 %}
<li>{{forloop.counter}}</li>
{% endif %}
{% endfor %}
Here is another solution, which might give you some more options if you're interested: Django Pagination Display Issue: all the page numbers show up.
And finally, here is a very nice tutorial on getting up to speed with the pagination that django offers out of the box: https://simpleisbetterthancomplex.com/tutorial/2016/08/03/how-to-paginate-with-django.html.
See if https://medium.com/#sumitlni/paginate-properly-please-93e7ca776432 helps. The code uses 10 for "neighbors" but you could change it to 5 when using the tag.

python pagination and search query on html

I am new to django.
I have a django template that renders mongodb values and accordingly paints the html. I am using pagination and search to display records.
Problem: How should I query search input in my html to display all the records which is currently masked with pagination in django.
This is how it looks with pagination.
And this is how I want to display with pagination
This is my code:
def index(request):
values = data.find()
paginator = Paginator(values, 12)
page = request.GET.get('page')
try:
listItem = paginator.page(page)
except PageNotAnInteger:
listItem = paginator.page(1)
except EmptyPage:
listItem = paginator.page(paginator.num_pages)
return render(request, 'product.html', {"values":values, "listItem":listItem})
This is my html
{% block content %}
<ul class="row catalog-list">
{% for value in values %}
<li class="col-xs-12 col-sm-6 col-md-4 col-lg-4">
<div>
<img src={{value.image_url_medium}}>
</div>
<div>
<h4 class="ellipsis-text catalog-item-name" tooltip={{value.name}}>{{value.name}}</h4>
<h5>Product Id: {{value.id_product}}</h5>
<h5>Category: {{value.catagory}}</h5>
<h5>Best Price: {{value.best_price}}</h5>
<h5>Best Price Vendor: {{value.best_price_vendor}}</h5>
<h5 class="ellipsis-text">Link:
<a href={{value.best_price_vendor_url}}>{{value.best_price_vendor_url}}</a>
</h5>
</div>
</li>
{% endfor %}
</ul>
<ul class="pagination">
<li class="step-links">
{% if listItem.has_previous %}
Previous
{% endif %}
<span class="current">
Page {{ listItem.number }} of {{ listItem.paginator.num_pages }}.
</span>
{% if listItem.has_next %}
Next
{% endif %}
</li>
</ul>
{% endblock %}
and jQuery:
$itemList = $('.catalog-list li');
console.log($itemList.length); //Prints 12
$("#filter").keyup(function(){
var filter = $(this).val();
if(filter==null){
$itemList.hide();
return;
}
var regex = new RegExp(filter, "i");
$itemList.each(function(){
if ($(this).find('h4').text().search(regex) < 0 && $(this).find('h5').text().search(regex) < 0) {
$(this).hide();
} else {
$(this).show();
}
});
});
I was new to django that time.
Its actually pretty simple here.
views.py
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from pymongo import MongoClient
register = template.Library()
port = 27017
client = MongoClient(port=port)
def people(request):
values = client.sdkUserIdDB.userIdColl.find() #getting all values from a database.
paginator = Paginator(values, 12) #putting all the values as a 12 slice so each page as 12 items from database.
page = request.GET.get('page')
try:
listItem = paginator.page(page)
except PageNotAnInteger:
listItem = paginator.page(1)
except EmptyPage:
listItem = paginator.page(paginator.num_pages)
return render(request, 'page.html', {"listItem":listItem})
templates > page.html
<ul class="pagination">
<li class="step-links">
{% if listItem.has_previous %}
Previous
{% endif %}
<span class="current">Page {{ listItem.number }} of {{ listItem.paginator.num_pages }}.</span>
{% if listItem.has_next %}
Next
{% endif %}
</li>
</ul>

badge notification by the number of new matches

I am trying to get a batch notification to work, but the badge throws several badges with the below code, and it does not show the number. I want the badge to display the number of content within several posts matches with an interest.
I am still a beginner at django, so please bear over with me, if this is a total bad approach.
interest.html
{% for item in interest %}
<ul class='nav nav-pills nav-stacked'>
<li><a href='/'>
<span class='badge pull-right'>
{% for word in post %}
{% if word == interest %}
{{ word.as_number }}
{% else %}
0
{% endif %}
{% endfor %}
</span>
{{ item.interest }}
</a></li>
</ul>
{% endfor %}
context_processors.py
def user_interest(request):
interest = Interests.objects.all()
interests_form = InterestsForm(request.POST or None)
post = Posts.objects.all()
if interests_form.is_valid():
new_interest = interests_form.save(commit=False)
new_interest.save()
#return HttpResponseRedirect('/')
#apparently it is not needed here
return {'interest': interest,
'interests_form': interests_form,
'post': post,
}
models.py
class Interests(models.Model):
interest = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
I'm not fully understanding, but part of your problem may be this part:
{% if word == interest %}
You're comparing a particular Post with all of your Interests (since 'interest' = Interests.objects.all()). At the very least I would change that to:
{% if word == item %}
As this iterates through your interest list (using 'item') and compares it to each 'word' in your post list.

Categories

Resources