ListView get_context_data - django

question about Django.
Would like to ask you guys if it's possible to use get_context_data in ListView?
I am interested in using the following template tags in my ListView:
{% if liked %}
<i class="fa-solid fa-thumbs-up"></i>
{% else %}
<i class="fa-regular fa-thumbs-up"></i>
{% endif %}
This works in my DetailView but I can't figure out how to implement it in ListView maybe you guys can help me?
This is my views.py
class PostList(generic.ListView):
model = Post
queryset = Post.objects.order_by('-created_on')
template_name = 'blog/blog.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'blog/post_detail.html'
def get_context_data(self, **kwargs):
context = super(PostDetail, self).get_context_data(**kwargs)
context['comments'] = self.object.comments.order_by('-created_on')
context['liked'] = self.object.likes.filter(id=self.request.user.id).exists()
return context
I'm testing get_context_data i ListView but can't get it to work.
I get the following message: This is the response error : AttributeError at /blog/ 'PostList' object has no attribute 'object'
Please need help :)

I think I need some help with how to use .annotate.
All I can think of is using template tags:
{% for comment in post.comments.all %}
{% if request.user == comment.author %}
Commented!
{% endif %}
{% endfor %}
But this doesn't work as expected :(

Related

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?

queryset when building django form

I am trying to get specific querysets based when a customer-specific form loads, showing only that customer's name (embedded as an ID field), its respective locations and users.
The idea is to select one user and any number of locations from a multichoice box.
I've tried to pass the ID as a kwarg but am getting a KeyError. I've tried the kwarg.pop('id') as found on the web and same issue. Any advice?
forms.py
class LocGroupForm(forms.ModelForm):
class Meta:
model = LocationsGroup
fields = ('group_name', 'slug', 'customer', 'location', 'user_id',)
def __init__(self, *args, **kwargs):
qs = kwargs.pop('id')
super(LocGroupForm, self).__init__(*args, **kwargs)
self.fields['customer'].queryset = Customers.objects.get(pk=qs)
self.fields['location'].queryset = CustomerLocations.objects.filter(customer_id=qs)
self.fields['user_id'].queryset = CustomerUsers.objects.filter(customer_id=qs)
here is my view. it's just a generic view
views.py
class LocGroupCreate(LoginRequiredMixin, CreateView):
form_class = LocGroupForm
template_name = 'ohnet/a_gen_form.html'
the template is a dry template I use for all my forms- admittedly something I mostly stole from a tutorial
{% extends "ohnet/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% load static %}
<div class="container">
<h1>{{ title }}</h1>
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" name="submit" value="Submit">
</form>
</div>
{% endblock content %}
This is the KeyError from the form load.
You need to pass a value for the id when constructing the LocGroupForm, you can do that by overriding get_form_kwargs:
class LocGroupCreate(LoginRequiredMixin, CreateView):
form_class = LocGroupForm
template_name = 'ohnet/a_gen_form.html'
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['id'] = …
return kwargs
You will need to fill in the … that specifies the value passed as id to the form. This might for example be self.request.user.pk, or a URL parameter with self.kwargs['name-of-url-parameter']

How to paginate a class-based list view with django-filters

Do you guys know how to paginate a generic class-based ListView that uses django-filters as a search bar? When I read some articles regarding this issue(which wasn't a lot for class-based views), it seems that django-filters and pagination don't work together very well. Here is my view:
class StudentListView(OrganisorAndLoginRequiredMixin, generic.ListView):
template_name = "leads/student_list.html"
context_object_name = "leads"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = StudentFilter(self.request.GET, queryset=self.get_queryset())
return context
def get_queryset(self):
organisation = self.request.user.userprofile
return Lead.objects.filter(organisation=organisation).order_by('first_name')
I would really appreciate it if you guys could tell me what code I need to write for my view as well as what code I need to add into my template to make pagination work. I don't think the code for the actual filter and the template is necessary, but if you guys need it, I can add it to this question. Thanks.
For additional information, I am going to add the following pagination code to my template:
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
previous
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
{% endif %}
</span>
</div>
{% endif %}
You should use FilterView that is provided by django-filter. Also this class inherits from MultipleObjectMixin so it is capable of performing pagination, so if you set paginate_by attribute on the class it will perform pagination too:
from django_filters.views import FilterView
class StudentListView(OrganisorAndLoginRequiredMixin, FilterView):
template_name = "leads/student_list.html"
context_object_name = "leads"
filterset_class = StudentFilter
paginate_by = 10 # Change as per your preference
def get_queryset(self):
organisation = self.request.user.userprofile
return Lead.objects.filter(organisation=organisation).order_by('first_name')

TemplateDoesNotExist at /edit-narration/13/edit/

Why is my narrate_update_form template not showing? And why am I getting
TemplateDoesNotExist at /narration/7/edit/
narrate_update_form
My views.py is:
class NarrateUpdate(UpdateView):
model = Narrate
fields = ['title', 'body']
template_name = 'narrate_update_form'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['narrate'] = Narrate.objects.get(pk=self.kwargs['pk'])
return context
On my narrate template I have this button:
Edit/Update
On the narrate_update_form.html, I have:
{% extends 'base.html' %}
{% block body %}
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update">
</form>
{% endblock body %}
Can anyone help me?
It'd be template_name = 'narrate_update_form.html', you need to add html there.
Also depending on where the template file actually is, you might need to specify a relative path to it.

Is it possible to render 2 queryset in ListView?

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.