How do I write a DetailView in Django, that has other related Queries?
Here is my example:
class DistributionDetailView(DetailView):
model = Distribution
template_name = 'projects/view_distribution.html'
def get_context_data(self, **kwargs):
context = super(DistributionDetailView,
self).get_context_data(**kwargs)
context['weekly_attendance'] = WeeklyAttendance.objects.filter(
distibution_name=Distribution)
context['sales_data'] = SalesData.objects.filter(
distibution_name=Distribution)
context['theatrical_release'] = TheatricalRelease.objects.filter(
distibution_name=Distribution)
return context
Distribution is the model class, you can't use it inside filter(). In the get_context_data method, you can access the current object with self.object, for example:
context['weekly_attendance'] = WeeklyAttendance.objects.filter(
distibution_name=self.object)
You can access the object with self.object in most generic views:
class DistributionDetailView(DetailView):
model = Distribution
template_name = 'projects/view_distribution.html'
def get_context_data(self, **kwargs):
context = super(DistributionDetailView,
self).get_context_data(**kwargs)
context['weekly_attendance'] = WeeklyAttendance.objects.filter(
distibution=self.object)
context['sales_data'] = SalesData.objects.filter(
distibution=self.object)
context['theatrical_release'] = TheatricalRelease.objects.filter(
distibution=self.object)
return context
Related
I have developed a context within a context.
here's my views.py:
class AgentClientListView(OrganizerAndLoginRequiredMixin, generic.ListView):
template_name = "agents/agent_client_list.html"
context_object_name = "clients"
def get_queryset(self):
queryset = Client.objects.filter(agent_id=self.kwargs['pk'], agent__isnull=False).order_by('company_name')
return queryset
however I need to add another context_object_name: "agent"
what would I do?
thank you in advance
You need to ovveride get_context_data:
def get_context_data(self, *args, **kwargs):
context = super(AgentClientListView, self).get_context_data(*args, **kwargs)
context['agents'] = <Your agent query>
return context
I'm using a django-filter form and it's filtering all objects for 'associated_portfolios' how can I make it so it only shows the user the objects they created?
Error message:
'StatsFilter' object has no attribute 'fields'
Filters.py
class StatsFilter(django_filters.FilterSet):
associated_portfolios = django_filters.ModelMultipleChoiceFilter(queryset=associated_portfolios)
class Meta:
model = Trade
fields = ['type', 'asset', 'symbol', 'broker', 'patterns', 'associated_portfolios']
def __init__(self, request, *args, **kwargs):
super(StatsFilter, self).__init__(*args, **kwargs)
self.fields['associated_portfolios'].queryset = Trade.objects.filter(user=request.user)]
views.py
class StatsView(LoginRequiredMixin, FilterView):
model = Trade
template_name = 'dashboard/stats.html'
filterset_class = StatsFilter
def get_context_data(self, **kwargs):
filter = StatsFilter(self.request.GET, queryset=self.get_queryset())
context = super().get_context_data(**kwargs)
context['filter'] = filter
context['get_users_trades'] = Trade.objects.get_users_trades('tj3admin')
context['get_largest_winning_trade'] = filter.qs.aggregate(max_value=Max('profit_loss_value_fees'))['max_value']
return context
Ah, now I remember: set the queryset argument of ModelMultipleChoiceFilter to a callable that accepts request as it's only argument:
def portfolio_filtered_queryset(request):
return Trade.objects.filter(user=request.user)
class StatsFilter(django_filters.FilterSet):
associated_portfolios = django_filters.ModelMultipleChoiceFilter(queryset=porfolio_filtered_queryset)
The view:
class StatsView(LoginRequiredMixin, FilterView):
model = Trade
template_name = 'dashboard/stats.html'
filterset_class = StatsFilter
def get_context_data(self, **kwargs):
# Must pass in request!
filter = StatsFilter(self.request.GET, queryset=self.get_queryset(), request=self.request)
context = super().get_context_data(**kwargs)
context['filter'] = filter
context['get_users_trades'] = Trade.objects.get_users_trades('tj3admin')
context['get_largest_winning_trade'] = filter.qs.aggregate(max_value=Max('profit_loss_value_fees'))['max_value']
return context
In django_filters.filters.QuerySetRequestMixin.get_request() the request instance is obtained from the parent. But I see no logic in django_filters.filterset.BaseFilterSet or concretes that tries to obtain the request through other means. So you must pass the request to the StatsFilter if you wish to make use of QuerySetRequestMixin.
How can i pass the context data which is coming from a forms.py to my views class which is using generic detailView, i need to pass forms.py to my product detail page.
Here is the code for my view class
class ProductView(generic.DetailView):
model = Product
cart_product_form = CartAddProductForm()
context = {'cart_product_form': cart_product_form}
template_name = 'shopping/product.html'
query_pk_and_slug = True
Please let me know if this is incorrect
Override get_context_data, and add the form to the context before returning it.
class ProductView(generic.DetailView):
model = Product
template_name = 'shopping/product.html'
query_pk_and_slug = True
def get_context_data(self, **kwargs):
context = super(ProductView, self).get_context_data(**kwargs)
cart_product_form = CartAddProductForm()
context['cart_product_form'] = cart_product_form
return context
I try to use class based views in Django. And I have such problem: I define a base class for a blog (BlogBaseView) and two other classes, that inherit it.
And in the second class(BlogIndexView) I want to make the search by get request, so I have override get method. It works, but if I don't make get request, it returns HttpResponse, however I want to return usual context (which BlogIndexView retunes without override get method).
What can I do?
class BlogBaseView(View):
def get_context_data(self, **kwargs):
context = super(BlogBaseView, self).get_context_data(**kwargs)
blog_categories = []
categories = BlogCategory.objects.all()
for category in categories:
blog_categories.append(tuple([category, category.get_number_of_category_items]))
context['name_page'] = 'blog'
context['tags'] = Tag.objects.all()
context['blog_categories'] = blog_categories
return context
class BlogIndexView(BlogBaseView, ListView):
queryset = Post.objects.all().order_by('-date_create')
template_name = 'index_blog.html'
context_object_name = 'posts'
def get(self, request):
if request.GET.get('tag'):
context = {
'posts' : Post.objects.filter(tags__name__in=[request.GET.get('tag')])
}
return render(request, self.template_name, context)
return HttpResponse('result')
class BlogFullPostView(BlogBaseView, DetailView):
model = Post
template_name = 'full_post.html'
pk_url_kwarg = 'post_id'
context_object_name = 'post'
Thanks!
ListView class also has a get_context_data method, so you should override that instead of get method. Using super you'll get access to BlogBaseView.get_context_data and then you can extended the result.
Here's how:
class BlogIndexView(BlogBaseView, ListView):
queryset = Post.objects.all().order_by('-date_create')
template_name = 'index_blog.html'
context_object_name = 'posts'
def get_context_data(self, **kwargs):
# use the (super) force Luke
context = super(BlogIndexView, self).get_context_data(**kwargs)
if self.request.GET.get('tag'):
context['posts'] = Post.objects.filter(tags__name__in=[self.request.GET.get('tag')])
return context
If you are overriding ListView then it's not a good idea to override the get method, as you will lose a lot of the ListView functionality.
In this case, it would be a better idea to override get_queryset, and do the search there.
def get_queryset(self):
queryset = super(BlogIndexView, self). get_queryset()
if request.GET.get('tag'):
queryset = queryset.filter(tags__name=request.GET['tag'])
return queryset
I'm trying to use request.session to create a 'recent' session key and add the product pages visited by the user to make it accesible in the template, here is my view, what would you guys recommend, I can't seem to go about doing this
class ProductDetail(DetailView):
model = Producto
template_name = 'productos/product_detail.html'
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(ProductDetail, self).get_context_data(**kwargs)
# Add in a QuerySet of featured products
context['product_list'] = Producto.objects.filter(featured=True).exclude(pk=self.object.pk)
return context
Thanks for your help!
thanks to Daniel Roseman for the clarification on how to call session from the class based generic view
class ProductDetail(DetailView):
model = Producto
template_name = 'productos/product_detail.html'
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(ProductDetail, self).get_context_data(**kwargs)
if not 'recent' in self.request.session or not self.request.session['recent']:
self.request.session['recent'] = [self.object.pk]
else:
recentList = self.request.session['recent']
recentList.append(self.object.pk)
self.request.session['recent'] = recentList
# Add in a QuerySet of featured products
context['product_list'] = Producto.objects.filter(featured=True).exclude(pk=self.object.pk)
context['recent_list'] = Producto.objects.filter(pk__in=recentList)
return context