Django Custom Queryset Using Listview if Parameters Exist in URL - python

I have a listview for my blog:
#views.py
class BlogListView(ListView):
model = Blog
template_name = 'blog/index.html'
context_object_name = 'blogs'
ordering = ['-date_posted']
paginate_by = 5
#urls.py
path('', BlogListView.as_view(), name='blog-index'),
In my model I have different type of blogs, such as video blog or text blog. my model is like this:
class Blog(models.Model):
TYPE = (
('Video', 'Video'),
('Text', 'Text'),
)
type = models.CharField(max_length=10, choices=TYPE, default='Text')
Now I want to use request.GET.get('type') to query different types. For example if I go to the url, 127.0.0.1:8000/?type=video I want only blog that are the type video to show. Is it possible to do this with only this listview, or do I have to create others. I need help with making of this feature.

Yes, you can implement this in the ListView by overriding the .get_queryset(…) method [Django-doc]:
class BlogListView(ListView):
model = Blog
template_name = 'blog/index.html'
context_object_name = 'blogs'
ordering = ['-date_posted']
paginate_by = 5
def get_queryset(self):
type = self.request.GET.get('type')
qs = super().get_queryset()
if type is not None:
return qs.filter(type__iexact=type)
return qs

Related

Django - ListView - list assigned images to the post

Hello I would like to list all images which were added to my post in my Blog application.
Models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = RichTextField(blank=True, null=True)
class PostImage(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE, related_name='postimages')
image = models.ImageField(upload_to='gallery/')
I guess I should override the get_queryset method but dont know how. Any ideas? Thanks.
EDIT:
Views.py
class PostGalleryView(ListView):
model = PostImage
template_name = 'blog/gallery.html'
context_object_name = 'images'
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
paginate_by = 10
def get_queryset(self):
public_posts = Post.objects.all()
return public_posts

How do I create a date range filter in a class based view?

My class based view in "views.py"
class PostListView(ListView):
model = Post.objects.filter(created__range=["2020-03-09", "2020-03-31"])
template_name = 'main/problems.html'
context_object_name = 'posts'
ordering = ['-created']
I have a variable "created" for when the post is created but dont know how to filter the post within a range.
The .model attribute [Django-doc] refers to the model class, but you can specify the .queryset attribute [Django-doc]:
class PostListView(ListView):
queryset = Post.objects.filter(created__range=['2020-03-09', '2020-03-31'])
template_name = 'main/problems.html'
context_object_name = 'posts'
ordering = ['-created']

success_url from UpdateView to DetailView with pk in django

I make my own group permission page self with ListView to show Django Group list with a link to DetailView with pk and then give the change link to change the permissions with UpdateView.
I want to make the success_url of UpdateView to DetailView with pk, how to do this.
my code like:
views.py
class GroupCreation(PermissionRequiredMixin, CreateView):
permission_required = 'add_group'
model = Group
form_class = GroupCreateModelForm
success_url = reverse_lazy('account:group_list')
template_name = 'accounts/groups/group_creation.html'
class GroupsListView(PermissionRequiredMixin, ListView):
permission_required = 'view_group'
allow_empty = True
model = Group
ordering = 'name'
template_name = 'accounts/groups/groups_list.html'
form = GroupCreateModelForm
extra_context = {'form': form, }
class GroupDetailView(PermissionRequiredMixin, DetailView):
permission_required = 'view_group'
model = Group
template_name = 'accounts/groups/group_detail.html'
class GroupUpdateView(PermissionRequiredMixin, UpdateView):
permission_required = 'change_group'
model = Group
fields = ('permissions',)
template_name = 'accounts/groups/group_update.html'
success_url = reverse_lazy('account:group_detail')
urls.py
path('groups/', views.GroupsListView.as_view(), name='group_list'),
path('groups/<int:pk>/', views.GroupDetailView.as_view(), name='group_detail'),
path('groups/<int:pk>/change/', views.GroupUpdateView.as_view(), name='group_change'),
path('groups/create/', views.GroupCreation.as_view(), name='group_creation'),
You can use the get_success_url method in your UpdateView instead of success_url attribute; This way you can access the edited object's pk:
def get_success_url(self):
return reverse_lazy('account:group_detail', kwargs={'pk': self.object.pk})

how to play with ordering in class based view

I'm using class based view and for instance
class PostListByMostViewedView(ListView):
model = Post
template_name = 'community/mostviewed_home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-views']
paginate_by = 5
Models.py
class Post(models.Model):
views = models.PositiveIntegerField(default=0)
then posts are listed by view. but
I have different model
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
I want to order by the number of post.
I thought this would work
ordering = ['-post.comment_set.count']
but this fails
no such column: post.comment_set.count
You can .annotate(..) [Django-doc] the Post objects with the number of items in the comment_set, and then .order_by(..) [Django-doc] that annotation:
from django.db.models import Count
class PostListByMostViewedView(ListView):
model = Post
queryset = Post.objects.annotate(
ncomments=Count('comment')
).order_by('-ncomments')
template_name = 'community/mostviewed_home.html'
context_object_name = 'posts'
paginate_by = 5
The nice thing is that every Post object from the queryset now has an extra attribute ncomments that contains the number of comments.

Django - Listing many different models in one page

I need to list different models in a single page/url.
#models.py
class Service(models.Model):
author = models.ForeignKey(User, related_name="services")
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
objects = ServiceQuerySet.as_manager()
class Carousel(models.Model):
author = models.ForeignKey(User, related_name="carousels")
title = models.CharField(max_length=255)
content = models.TextField()
objects = CarouselQuerySet.as_manager()
This is my views, this way are listed in different pages, I tried to join the queryset, but got no success.
#views.py
class ServiceListView(generic.ListView):
model = models.Service
queryset = models.Service.objects.published()
class CarouselListView(generic.ListView):
model = models.Carousel
queryset = models.Carousel.objects.published()
This is my urls.py, this listing only those services.
urlpatterns = patterns('',
url(r'^$', views.ServiceListView.as_view(), name="service_list"),
url(r'^$', views.CarouselListView.as_view(), name="carousel_list"),
)
I need the two lists appear on the same page. How can I accomplish this task?
What about passing it through the context?
from .models import Service,Carousel
class ServiceListView(generic.ListView):
model = Service
queryset = Service.objects.published()
def get_context_data(self, **kwargs):
context = super(ServiceListView, self).get_context_data(**kwargs)
context['carousel_list'] = Carousel.objects.published()
return context

Categories