How do i import this list_filter into my html? do you have any documentation that easy to follow and easy to understand? is it possible?
class ArticleListView(ListView):
model = StudentsEnrollmentRecord
s=StudentsEnrollmentRecord.objects.all()
paginate_by = 50 # if pagination is desired
searchable_fields = ["Student_Users", "id", "Section"]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['now'] = timezone.now()
return context
You can use template tags to loop your object and populate your html:
https://docs.djangoproject.com/en/3.0/ref/templates/builtins/
To give you a kickstart:
<ul>
{% for filter in s %}
<li>{{ filter.Student_Users }}</li>
{% endfor %}
</ul>
This will basically create one <li> per each item in your queryset.
Make sure that the required data is returned properly from your view via the context:
context = {
'queryset': s,
}
return (context)
Recently I installed django-taggit and included in the post model. I did the views and urls files and no error. On the home page I get a few posts and 10 tags related to posts. When I click on one of the tags it goes to the right slug but the page is blank. What am I missing here? Any help would be appreciated.
This is my code, views.py, urls.py, home.html
def home(request):
tutorial_list = Post.objects.all().order_by('-id')[:3]
context = {
'tutorial_list': tutorial_list,
}
return render(request, "home.html", context)
class TagMixin(object):
def get_context_data(self, **kwargs):
context = super(TagMixin, self).get_context_data(**kwargs)
context['tags'] = Tag.objects.all()
return context
class TagIndexView(TagMixin, ListView):
template_name = 'home.html'
model = Post
context_object_name = 'post'
def get_queryset(self):
return Post.objects.filter(tags__slug=self.kwargs.get('slug'))
'''urls.py'''
path('tag/<slug:slug>/', views.TagIndexView.as_view(), name='tagged'),
'''home.html'''
{% for tutorial in tutorial_list %}
{{ tutorial.title }}
{% endfor %}
{% for tag in tags %}
<li>{{ tag.name }}</li>
{% endfor %}
The context_object_name of TagIndexView does not match the variable name you're iterating over in home.html - the template is using tutorial_list so context_object_name should be 'tutorial_list' instead of 'post'.
class TagIndexView(TagMixin, ListView):
template_name = 'home.html'
model = Post
context_object_name = 'tutorial_list'
def get_queryset(self):
return Post.objects.filter(tags__slug=self.kwargs.get('slug'))
I am new to django and recently read a tutural that describes the usage of class based view. But when I try to render 2 different queryset (all data and filterd data) to the same template, I can't find the solution for display 2 different queryset. Can anyone suggest the best solution about this?
I know writing the function based view is much easy for this, but I hope it can be done by Class based view, thank you
#in view.py
from django.views.generic import ListView
from books.models import Book
class BookListView(generic.ListView):
model = Book
context_object_name = 'my_book_list'
queryset = Book.objects.all()
template_name = 'books/my_arbitrary_template_name_list.html'
# queryset = Book.objects.filter(title='war')?
#in templage.py
#Main content
<div class="main_content">
<h1>All War</h1>
<ul>
{% for book in book_list %}
<li>
{{book.title}}
</li>
{% for endfor %}
</ul>
</div>
#Sidebar
<div class="sidebar">
<h1>All War</h1>
<ul>
{% for book in book_list %}
<li>
{{book.title}}
</li>
{% for endfor %}
</ul>
</div>
You should look into get_context_data to add additional queries you want.
The view might look something like this
class BookListView(generic.ListView):
model = Book
context_object_name = 'my_book_list'
queryset = Book.objects.all()
template_name = 'books/my_arbitrary_template_name_list.html'
def get_context_data(self, **kwargs):
context = super(BookListView, self).get_context_data(**kwargs)
context['second_queryset'] = # YOUR QUERY HERE
return context
For this example the second query is second_queryset and it can be accessed in the html template as {{second_queryset}}. You can add more if you did the same for more queries.
def get_context_data(self, **kwargs):
context = super(BookListView, self).get_context_data(**kwargs)
context['second_queryset'] = # YOUR QUERY HERE
context['third_queryset'] = # YOUR QUERY HERE
...
return context
You can learn about it more in here.
I'm using the standard django paginator in my generic view like this:
def get_context_data(self, **kwargs):
context = super(ArchivePagedView, self).get_context_data(**kwargs)
article_list = Article.published
#=====================================
paginator = Paginator(article_list, self.paginate_by)
page = self.request.GET.get('page')
try:
article_list = paginator.page(page)
except PageNotAnInteger:
article_list = paginator.page(1)
except EmptyPage:
article_list = paginator.page(paginator.num_pages)
if 'reverse' in self.request.GET:
article_list = article_list.reverse() #This doesn't work!
else:
article_list = article_list.all()
context['article_list'] = article_list
return context
As you can see I want to override article_list with the same list, but in reversed direction, if reverse is in the URL in behind the question mark. That information I get by 'reverse' in self.request.GET.
But I get an error: AttributeError: 'Page' object has no attribute 'reverse'. How do I reverse this? (I don't want to have duplicated code in my template.)
Before I fixed this by making an extra context variable (context['reverse']) which says whether the list should be reversed or not, and then I used duplicated code like this:
{% if reverse %}
{% for article in article_list reversed %}
... some code
{% endfor %}
{% else %}
{% for article in article_list %}
... the same code
{% endfor %}
{% endif %}
I wonder if there was no better solution.
Try this
article_list.object_list = list(reversed(article_list.object_list))
I'm fairly new to Wagtail, and I am in the process of creating a site that will have a Resources (blog) section and I'm not sure how to implement pagination so that there are only 5 posts on each page and the user has to click a number (1, 2, 3, etc.) to go to the next page to see the next 5 posts.
I have this in my template for the pagination section of the resource/blog index page:
<ul class="pagination">
<li><i class="fa fa-angle-left"></i></li>
<li class="active">1</li>
<li>2</li>
<li>3</li>
<li><i class="fa fa-angle-right"></i></li>
</ul>
What code do I need to incorporate to make this functional? Thanks in advance.
Django provides the module django.core.paginator for this purpose: https://docs.djangoproject.com/en/1.10/topics/pagination/ . Using this within Wagtail is very similar to the examples in the Django documentation - the only real difference is that when you're setting up the Paginator object to be passed to the template, you do that with a get_context method on the page model, instead of a view function. Your model definition will look something like this:
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
class ResourceIndexPage(Page):
# ...
def get_context(self, request):
context = super(ResourceIndexPage, self).get_context(request)
# Get the full unpaginated listing of resource pages as a queryset -
# replace this with your own query as appropriate
all_resources = ResourcePage.objects.live()
paginator = Paginator(all_resources, 5) # Show 5 resources per page
page = request.GET.get('page')
try:
resources = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
resources = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
resources = paginator.page(paginator.num_pages)
# make the variable 'resources' available on the template
context['resources'] = resources
return context
Within your template, you can now loop over the items using {% for resource in resources %}, and display the pagination links as follows:
<ul class="pagination">
{% if resources.has_previous %}
<li><i class="fa fa-angle-left"></i></li>
{% endif %}
{% for page_num in resources.paginator.page_range %}
<li {% if page_num == resources.number %}class="active"{% endif %}>{{ page_num }}</li>
{% endfor %}
{% if resources.has_next %}
<li><i class="fa fa-angle-right"></i></li>
{% endif %}
</ul>
I very much appreciate that you got me here - thanks so much for the assist. I had to make some adjustments to make it work. Here's the model if anyone comes across the same issue:
class NewsIndexPage(Page):
intro = RichTextField(blank=True)
def get_context(self, request):
context = super(NewsIndexPage, self).get_context(request)
# Get the full unpaginated listing of resource pages as a queryset -
# replace this with your own query as appropriate
blogpages = self.get_children().live().order_by('-first_published_at')
paginator = Paginator(blogpages, 3) # Show 3 resources per page
page = request.GET.get('page')
try:
blogpages = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
blogpages = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
blogpages = paginator.page(paginator.num_pages)
# make the variable 'resources' available on the template
context['blogpages'] = blogpages
return context
...and here's the HTML:
<ul class="pagination">
{% if blogpages.has_previous %}
<li>
<i class="fa fa-angle-left"></i>
</li>
{% endif %}
{% for page_num in blogpages.paginator.page_range %}
<li {% if page_num == blogpages.number %} class="active"{% endif %}>
{{ page_num }}
</li>
{% endfor %}
{% if resources.has_next %}
<li>
<i class="fa fa-angle-right"></i>
</li>
{% endif %}
</ul>
It works like a charm - and adds to the learning curve!
In case it's useful to anyone, I wanted this to work as closely as possible to the class-based view ListView, and so I ended up with this:
from django.core.paginator import Paginator, InvalidPage
from django.http import Http404
from django.utils.translation import gettext as _
from wagtail.core.models import Page
class ArticleListPage(Page):
# Some Page variables set here. #
# Pagination variables:
paginator_class = Paginator
paginate_by = 10
page_kwarg = 'page'
paginate_orphans = 0
allow_empty = False
def get_context(self, request):
context = super().get_context(request)
queryset = Page.objects.live()
paginator, page, queryset, is_paginated = self.paginate_queryset(
queryset, self.paginate_by, request)
context.update({
'paginator': paginator,
'page_obj': page,
'is_paginated': is_paginated,
'object_list': queryset,
})
return context
def paginate_queryset(self, queryset, page_size, request):
"""
Adapted from the ListView class-based view.
Added the request argument.
"""
paginator = self.paginator_class(
queryset,
self.paginate_by,
orphans=self.paginate_orphans,
allow_empty_first_page=self.allow_empty)
page_kwarg = self.page_kwarg
page = request.GET.get(page_kwarg) or 1
try:
page_number = int(page)
except ValueError:
if page == 'last':
page_number = paginator.num_pages
else:
raise Http404(_("Page is not 'last', nor can it be converted to an int."))
try:
page = paginator.page(page_number)
return (paginator, page, page.object_list, page.has_other_pages())
except InvalidPage as e:
raise Http404(_('Invalid page (%(page_number)s): %(message)s') % {
'page_number': page_number,
'message': str(e)
})
This will give you the same paginator, page_obj, is_paginated and object_list variables in your template that you would get with a normal Django ListView.
(Using python 3, Django 2.1 and Wagtail 2.3.)