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
Related
I have this function-based view doing what I need it to do - get the list of all Posts filed under s specific Category and reach that list by going to example.com/economics/ (where economics is the slug od that specific Category). There I would find the list of all my posts filed under Economics category and create links so I can click on them and go to a single post page.
Currently, my FBV looks like this:
def category_detail(request, category_detail_slug=None):
categories = Category.objects.all()
#Show only published posts
posts = Post.objects.filter(status__exact='1')
if category_detail_slug:
category = get_object_or_404(Category, slug=category_detail_slug)
posts = posts.filter(category=category)
return render(request, 'blog/category/single.html', {'category_detail_slug': category_detail_slug,
'category': category,
'categories': categories,
'posts': posts})
I started creating my CBV like this:
class CategoryDetailView(DetailView):
model = Category
template_name = 'blog/category/single.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
I know I need to pass some context, but somehow this keeps failing me.
My URL for this is defined as such:
path('<slug:category_detail_slug>/', views.CategoryDetailView.as_view(), name="single_category")
you can do it in following way
class CategoryDetailView(DetailView):
model = Category
slug_url_kwarg = 'category_detail_slug'
template_name = 'blog/category/single.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
posts = Post.objects.filter(status__exact='1')
context['posts'] = posts.filter(category=category)
return context
I think I got it - I need to return category as self.object so it all looks like this;
class CategoryDetailView(DetailView):
model = Category
slug_url_kwarg = 'category_detail_slug'
template_name = 'blog/category/single.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
posts = Post.objects.filter(status__exact='1')
category = self.object
context['posts'] = posts.filter(category=category)
return context
But you helped out a lot and I will mark your response as an answer!
Here is what I have currently.
views.py
class MultipleModelView(generic.TemplateView):
template_name = 'upload/home.html'
# #login_required(redirect_field_name='notloggedin.html')
def get_context_data(self, **kwargs):
if self.request.user.is_authenticated:
context = super(MultipleModelView, self).get_context_data(**kwargs)
context['jobs'] = Job.objects.filter(author=self.request.user).order_by('-created_at')
context['posts'] = devpost.objects.all().order_by('-created_at')
context['subcounter'] = SubCounter()
context['inprogcounter'] = InProgCounter()
context['fincounter'] = FinCounter()
return context
else:
context = super(MultipleModelView, self).get_context_data(**kwargs)
# context['jobs'] = Job.objects.filter(author=self.request.user).order_by('-created_at')
context['posts'] = devpost.objects.all().order_by('-created_at')
return context
class PostCreateView(LoginRequiredMixin,generic.CreateView):
model = Job
fields = ['patient_name', 'location']
def form_valid(self, form):
form.instance.author = self.request.user
id = randomStringDigits(5)
form.instance.identifier = id
sleepy.delay(id=id)
return super().form_valid(form)
The reason why it looks like this is because I have a page where I have multiple models on it.
The job model is updated in this file once it is created.
tasks.py
#shared_task
def sleepy(id=None):
MyModel = apps.get_model('upload','Job')
working_with = MyModel.objects.get(identifier=id)
working_with.status = "In Progress"
sleep(30)
working_with.status = "Finished"
return None
Essentially, once a user makes a post, it gets sent to an asynchronous task where I change an attribute in the model. The model is updated properly, but I want the detail view to change once the database updates. Is this possible?
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
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