Pagination Not Working for multiple query - django

I am using pagination but is not woking. I have used with get_queryset() and it works. Why it is not working in get_context_view()
class UserListView(LoginRequiredMixin, generic.TemplateView):
template_name = 'users/users.html'
paginate_by = 1
def get_context_data(self, **kwargs):
context = super(UserListView, self).get_context_data(**kwargs)
context['companies'] = Company.objects.exclude(company_is_deleted=True).exclude(company_name='Apollo')
context['users'] = User.objects.filter(userprofile__user_role__id=2).exclude(
Q(is_superuser=True) |
Q(userprofile__user_is_deleted = True)|
Q(userprofile__user_company__company_is_deleted=True)
)
query = self.request.GET.get('query')
if query:
list_query = context['users']
context['users'] = list_query.filter(userprofile__user_company__company_name__icontains=query)
return context

TemplateView does not provide us with pagination. we can use ListView. It's not recommended to paginate in get_context_data method.
For pagination you should use get_queryset method.
Example:
class UserListView(LoginRequiredMixin, generic.ListView):
paginate_by = 10
def get_queryset(self, **kwargs):
queryset = User.objects.filter(userprofile__user_role__id=2).exclude(
Q(is_superuser=True) |
Q(userprofile__user_is_deleted = True)|
Q(userprofile__user_company__company_is_deleted=True)
)
query = self.request.GET.get('query')
if query:
queryset = list_query.filter(
userprofile__user_company__company_name__icontains=query)
return queryset
If you use ListView then in the template you can access users with name object_list.

Related

Pass get_queryset in Context

Need help on passing the returned value from get_queryset to the context for rendering, I am reading the Django documentation on Class-based Views and I keep getting the same error name 'querySet' is not defined, any insight on what I'm doing wrong would be appreciated.
class SearchPropertyListView(ListView):
template_name = "search/search_list.html"
def get_queryset(self):
querySet = Property.objects.all()
city_or_neighborhood = self.request.GET.get('city_or_neighborhood')
category = self.request.GET.get('category')
purpose = self.request.GET.get('purpose')
if city_or_neighborhood != '' and city_or_neighborhood is not None:
querySet = querySet.filter(Q(city__title__icontains=city_or_neighborhood)
| Q(neighborhood__title__icontains=city_or_neighborhood)
).distinct()
elif category != '' and category is not None:
querySet = querySet.filter(category__title=category)
elif purpose != '' and purpose is not None:
querySet = querySet.filter(purpose__title=purpose)
return querySet
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
city = City.objects.all().annotate(
num_property=Count("property")).order_by("-num_property")
categories = Category.objects.all()
purposes = Purpose.objects.all()
featured = list(Property.objects.filter(featured=True))
shuffle(featured)
context['city'] = city
context['categories'] = categories
context['featured'] = featured
context['purposes'] = purposes
context['querySet'] = querySet
return context
In your get_context_data(), you have querySet which is not defined:
def get_context_data(self, *args, **kwargs):
.....
context['purposes'] = purposes
context['querySet'] = querySet <----- Here
return context
So, you should define your querySet like:
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
city = City.objects.all().annotate(
num_property=Count("property")).order_by("-num_property")
categories = Category.objects.all()
purposes = Purpose.objects.all()
featured = list(Property.objects.filter(featured=True))
querySet = self.get_queryset()
shuffle(featured)
context['city'] = city
context['categories'] = categories
context['featured'] = featured
context['purposes'] = purposes
context['querySet'] = querySet
return context
*Note:- If you are expecting querySet from get_queryset(), then know that these are two different methods and you defined querySet locally. Or, you have to get that from self.get_queryset() as mentioned by #OlegŠ¢.

How to make a Django filter display only to some users?

I'm working on a Django project, and want to know how can I make it so that a filter field displays only if the user is a superuser. My filter looks like this:
class OrderFilter(FilterUserMixin):
customer = django_filters.CharFilter(label='Cliente', method='filter_name')
def filter_name(self, queryset, name, value):
queryset = queryset.filter(customer__phone__icontains=value)
return queryset
class Meta:
model = Order
fields = ("store", "customer", "date")
filter_overrides = {
models.CharField: {
'filter_class': django_filters.CharFilter,
'extra': lambda f: {
'lookup_expr': 'icontains',
},
}
}
All normal users should be able to filter by customer and date, but only superusers should be able to filter by store, the rest of users should always see the orders of a single store, so no filtering the store.
I don't know how can I accomplish this, I'm using this view:
class OrderTableView(LoginRequiredMixin, PagedFilteredTableView):
model = Order
table_class = OrderTable
template_name = 'order/order_list.html'
paginate_by = 50
filter_class = OrderFilter
formhelper_class = OrderFilterFormHelper
exclude_columns = ('actions',)
export_name = 'orders'
def get_queryset(self, **kwargs):
qs = super(OrderTableView, self).get_queryset()
if self.request.user.profile.store is not None and self.request.user.is_superuser is False:
qs = qs.filter(store=self.request.user.profile.store)
qs = qs.filter(total__gt=0).filter(address__isnull=False).filter(location__isnull=False)
return qs
one of the ways to solve it:
class OrderFilter(FilterUserMixin):
# omit the other codes
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.request.user.is_superuser and self.filters.get('store'):
self.filters.pop('store')
then drop the related code for the superuser.

How to add pagination in Classed Based View with get_context_data

I want to add pagination to my List View. I have used paginated_by=10 but it not working. Please help me to add pagination to my view in my template. What HTML should i put in my template
View.py
class CompanyListView(LoginRequiredMixin, generic.TemplateView):
template_name = 'superadmin/company/company.html'
def get_context_data(self, **kwargs):
context = super(CompanyListView, self).get_context_data(**kwargs)
context['companies'] = Company.objects.exclude(company_name='Apollo').exclude(company_is_deleted = True).annotate(number_of_company_users=Count('userprofile'))
return context
You could use ListView instead of TemplateView.
Here is how.
class CompanyListView(LoginRequiredMixin, generic.ListView):
template_name = 'superadmin/company/company.html'
queryset = Company.objects.all()
context_object_name = 'companies'
paginate_by = 10
def get_queryset(self):
return (
self.queryset.exclude(company_name='Apollo')
.exclude(company_is_deleted =True)
.annotate(number_of_company_users=Count('userprofile'))
)

objects filter on base of url request

I have two similar classes, query filter is county code DE or NL.
Is possible to make a objects filter on base of url name and keep only one class? For example, if i point my browser to
127.0.0.1:8000/germany
django will call to filter
feed__country__name='DE'
and
127.0.0.1:8000/netherland
will use
feed__country__name='NL'?
My URL:
url(r'^netherland/$', NLFeedList.as_view(), name='nl'),
url(r'^germany/$', DEFeedList.as_view(), name='de'),
VIEWS:
class NLFeedList(PaginationMixin, ListView):
model = FeedItem
template_name = 'nl_feed.html'
context_object_name = 'feed_items'
paginate_by = 20
def get_queryset(self):
items = FeedItem.objects.filter(feed__country__name='NL')
if self.kwargs.get('category', None):
return items.category(self.kwargs.get('category'))
return items
def get_context_data(self, **kwargs):
context = super(NLFeedList, self).get_context_data(**kwargs)
context['categories'] = Category.objects.filter(country__name='NL')
return context
class DEFeedList(PaginationMixin, ListView):
model = FeedItem
template_name = 'de_feed.html'
context_object_name = 'feed_items'
def get_queryset(self):
items = FeedItem.objects.filter(feed__country__name='DE')
if self.kwargs.get('category', None):
return items.category(self.kwargs.get('category'))
return items
def get_context_data(self, **kwargs):
context = super(DEFeedList, self).get_context_data(**kwargs)
context['categories'] = Category.objects.filter(country__name='DE')
return context
You can do something like:
urls.py
url(r'^(?P<country>germany|netherland)/$', FeedList.as_view(), name='feedlist')
and the view:
class FeedList(PaginationMixin, ListView):
model = FeedItem
context_object_name = 'feed_items'
match = {'germany':'DE','netherland':'NL'}
def get_queryset(self):
code = self.match[self.kwargs['country']]
items = FeedItem.objects.filter(feed__country__name=code)
self.template_name = '%s_feed.html' % code.lower()
if self.kwargs.get('category', None):
return items.category(self.kwargs.get('category'))
return items
def get_context_data(self, **kwargs):
context = super(FeedList, self).get_context_data(**kwargs)
context['categories'] = Category.objects.filter(country__name=self.match[self.kwargs['country']])
return context
Also, perhaps you don't need two templates else only one, in this case just remove this line self.template_name = '%s_feed.html' % code.lower() and set the template_name accordingly.
Change your url to
url(r'^(?P<country>netherland|germany)/$', NLFeedList.as_view(), name='nl'),
Then access this new <country> parameter in your view using
country = self.kwargs['country']
Then do the necessary if country = '...': code block in your view.

Dynamic field names in Django Mixin

I have these class based ListView's which I would like to filter by date. I have a simple mixin
to display the filterform, which works great:
class MonthYearFormMixin(object):
def get_context_data(self, **kwargs):
context = super(MonthYearFormMixin, self).get_context_data(**kwargs)
context['monthyearform'] = MonthYearForm(self.request.GET)
return context
I would like to extend the functionality of this mixin to include the queryset filtering, but my models
have different date fields that need to be filtered on, one might be start_date, another might be
invoice_date. Of course someone might say, "rename them all 'date'", but that's not representative
of my models and furthermore, I might have a model with start_date and end_date, but only want to filter
on start_date. Here are my views:
class SentList(MonthYearFormMixin, ListView):
model = Sent
context_object_name = 'object'
template_name = 'sent_list.html'
def get_queryset(self):
qs = self.model.objects.all()
if 'month' in self.request.GET:
if int(self.request.GET['month']) > 0:
qs = qs.filter(start_date__month=self.request.GET['month'])
if 'year' in self.request.GET:
if int(self.request.GET['year']) > 0:
qs = qs.filter(start_date__year=self.request.GET['year'])
return qs
class ReceivedList(MonthYearFormMixin, ListView):
model = Received
context_object_name = 'object'
template_name = 'received_list.html'
def get_queryset(self):
qs = self.model.objects.all()
if 'month' in self.request.GET:
if int(self.request.GET['month']) > 0:
qs = qs.filter(invoice_date__month=self.request.GET['month'])
if 'year' in self.request.GET:
if int(self.request.GET['year']) > 0:
qs = qs.filter(invoice_date__year=self.request.GET['year'])
return qs
The only thing that's different is the name of the date field, so it's frustrating to have to repeat
this code.
Why not create a member variable called date_field_name where you store the name of the field names which should be processed by your QuerySet processor mixin?
This list would be defined in the class which uses the mixin.
Something like
class MonthYearFormMixin(object):
def get_context_data(self, **kwargs):
context = super(MonthYearFormMixin, self).get_context_data(**kwargs)
context['monthyearform'] = MonthYearForm(self.request.GET)
return context
def get_queryset(self):
qs = self.model.objects.all()
if 'month' in self.request.GET:
if int(self.request.GET['month']) > 0:
kwargs = {('%s__month' % self.date_field_name): self.request.GET['month']}
qs = qs.filter(**kwargs)
if 'year' in self.request.GET:
if int(self.request.GET['year']) > 0:
kwargs = {('%s__year' % self.date_field_name): self.request.GET['year']}
qs = qs.filter(**kwargs)
return qs
your views would look like this:
class SentList(MonthYearFormMixin, ListView):
model = Sent
context_object_name = 'object'
template_name = 'sent_list.html'
date_field_name = 'start_date'