Django CBV ListView, accessing both paginated and unpaginated results - django

I built a list view using generic view class ListView with pagination and search functionality. Now I want to include in the same page a map with markers for all the results, without pagination.
Is there a way to reach both paginated and unpaginated results without having to do a duplicate query?

We can do it by override the method def get_context_data(self, **kwargs). It takes only a single query.
class MyListview(ListView):
def get_context_data(self, **kwargs):
kwargs['obj_list'] = list(kwargs['obj_list'])
my_obj_list = kwargs['obj_list']
context = super(MyListview, self).get_context_data(**kwargs)
context['my_obj_list'] = my_obj_list
return context

Related

Django-filters resets after using the UpdateView

I have a Model with a lot of entries, so I'm using django-filters to filter the model, I initially load an empty table and from there I use the filter to view the items.
Everything works fine, the page loads initially with no entry, after I filter, django shows the correct items.
The Url gets a parameter: /retetabloc/?acordcadru=532(532 is the filter) but when I try to update an entry, the filter resets(the parameter is still in the URL) and the whole db is loaded.
I don't quite understand how to pass the filter parameter to the RetetaBlocUpdate, so that after the update is done it returns to the filtered items like in the ListView.
views.py
class RetetaBlocListview(LoginRequiredMixin, CoreListView):
model = RetetaBloc
def get_queryset(self, *args, **kwargs):
pdb.set_trace()
acordcadru = self.request.GET.get("acordcadru")
queryset = RetetaBloc.objects.filter(acordcadru=acordcadru)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = RetetaBlocFilter(self.request.GET, queryset=self.get_queryset())
pdb.set_trace()
return context
class RetetaBlocUpdate(LoginRequiredMixin, AjaxUpdateView):
model = RetetaBloc
form_class = RetetaBlocForm
Thank you.
If you'd like filters to be remembered you could add them to a session variable instead. That way filters would be recalled even if they didn't go back directly from the update page (and you'd wouldn't have redundant URL querystring on pages where they weren't needed).
Something like:
def get_queryset(self, *args, **kwargs):
pdb.set_trace()
#check for new filter in URL first
acordcadru = self.request.GET.get("acordcadru")
#if nothing check for session variable
if not acordcadru:
acordcadru = self.request.session.get('acordcadru')
#if something in URL querystring, set it in session variable
else:
self.request.session['acordcadru'] = acordcadru
queryset = RetetaBloc.objects.filter(acordcadru=acordcadru)
return queryset

adding detail information to django listview object in template

I have a listview in which I'm hoping to insert additional details about the object (activity duration and average power) in the same row as the link to the object detail (the best way to describe it would be that I want some detailview attributes inserted into the listview). At the moment, the best I can achieve is a separate context dictionary listed below the object_list, as shown in this screen shot:
And the following is my listview:
class RideDataListView(LoginRequiredMixin, ListView):
model = RideData
context_object_name='object_list'
template_name='PMC/ridedata_list.html'
def get_queryset(self):
queryset = super(RideDataListView, self).get_queryset()
return queryset
def get_context_data(self, *args, **kwargs):
model = RideData
context = super(RideDataListView, self).get_context_data(*args, **kwargs)
records = list(RideData.objects.all().values())
actdict2={}
id=[]
ap=[]
actdur=[]
for record in records:
actdf=pd.DataFrame.from_dict(record)
id.append(actdf['id'].iloc[0])
ap.append(actdf['watts'].mean())
actdur.append(str(timedelta(seconds=len(actdf['time']))))
actdf2=pd.DataFrame()
actdf2['id']=id
actdf2['ap']=ap
actdf2['actdur']=actdur
actdict2=actdf2.to_dict('records')
context['actdict']=actdict2
context['actdur']=actdur
return context
What I haven't been able to nail down in my research is if there is a way to either a) annotate the queryset with stuff from context or b) loop through the context dictionary 'actdict' within the object_list loop (doesn't seem possible based on some attempts) or c) include individual lists (ap and actdur as additions to to query. Just curious for some additional leads to add some more object detail to the basic listview.
Your context is intended to contain your data, but the way it is displayed rely on the HTML template you will use : https://docs.djangoproject.com/en/3.0/topics/templates/
The actual solution to this was to add to queryset object within def get_queryset
def get_queryset(self):
queryset = super(RideDataListView, self).get_queryset()
for obj in queryset:
record=list(obj.watts)
actdf=pd.DataFrame()
actdf['watts']=record
obj.actdur=str(timedelta(seconds=len(actdf['watts'])))
obj.ap=actdf['watts'].mean()
return queryset
This returned the additional summary information I wanted to include in the listview that is also used in detailview

How to know what context data returned by any GCBV in django?

Is there any way to know the dictionary returned by any GCBV other than looking at the code.
context_dict
I had to look at the code at django.views.generic.list to know that ListView returns this context dictionary.
Is there any other fast way to know
As per Django Docs, the default is object_list, but can be set using
context_object_name = 'your_context_name'
If you want to add some other context
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['your_other_context_name'] = Model.objects.all() # or whatever you want to query
return context

Filter model based of context data using django filter

I have a detail view of a model that I want to display together with a list of products and Im trying to integrate django_filter within this view.
Error Message
TypeError at /collections/christmas/?category=mens,
get context data takes exactly 2 arguments (1 given)
Filter
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
fields = ['categories']
Detail View
class collection_detail(DetailView):
model = Collection
def get_context_data(self, request, **kwargs):
context = super(collection_detail, self).get_context_data(**kwargs)
context['collection_list'] = ProductFilter(request.GET, queryset=Product.objects.filter(collection=self.object.id).filter(structure='parent'))
return context
How i intend it to work
The category filter is pre-defined in a list of links, so when the user clicks on a collection related to a specific category the url of the detail view would look like /collections/christmas/?category=mens .
What am I specifically doing wrong here? Is it possible to even do this?
You're missing *args in your overridden method.
class collection_detail(DetailView):
model = Collection
def get_context_data(self, *args, **kwargs):
context = super(collection_detail, self).get_context_data(*args, **kwargs)
context['collection_list'] = ProductFilter(self.request.GET, queryset=Product.objects.filter(collection=self.object.id).filter(structure='parent'))
return context

How do I get django url parameters from a view mixin?

Exactly what the title says. I have a mixin that needs to pull in the id of a model field in order to be useful. I assume the easy way to do that would be to pull it from the URL.
class StatsMixin(ContextMixin):
def get_stats_list(self, **kwargs):
# the ??? is the problem.
return Stats.objects.filter(id=???).select_related('url')
def get_context_data(self, **kwargs):
kwargs['stats'] = self.get_stats_list()[0]
print kwargs
return super(StatsMixin, self).get_context_data(**kwargs)
Here's the view implementation for reference.
class ResourceDetail(generic.DetailView, StatsMixin):
model = Submissions
template_name = 'url_list.html'
queryset = Rating.objects.all()
queryset = queryset.select_related('url')
You can access URL parameters in Django by using, self.args and self.kwargs.