I have a function-based view I'm trying to convert to a class-based view(DetailView). The function-based view is the equivalent of DetailView in CBV. How do I go about this?
This is the function based-view
def show_post(request, post):
"""A View to display a single post.
The post variable here is the slug to a post.
The slug to a post may possibly be a duplicate. So we filter all posts by
the slug (which is the 1st variable here)
And then select the first post returned by the filter queryset.
The first post returned is, of course, the post we are trying to view.
"""
post = Post.objects.filter(slug=post)
if post.exists():
post = post[0]
else:
return HttpResponseRedirect('/blog/')
count_visits = None
unique_views = set()
if request.user.is_authenticated:
post_views = PostView.objects.filter(post=post)
count_visits = post_views.count()
for post_view in post_views:
unique_views.add(post_view.ip)
else:
post_view = PostView(post=post, ip=request.META.get('REMOTE_ADDR',''),
http_host=request.META.get('HTTP_HOST', ''),
http_referrer=request.META.get('HTTP_REFERER',''),
http_user_agent=request.META.get('HTTP_USER_AGENT', ''),
remote_host=request.META.get('REMOTE_HOST', ''))
post_view.save()
c = {
'post': post,
'comments': comments,
'new_comment': new_comment,
'similar_posts': similar_posts,
'count_visits': count_visits,
'unique_views': unique_views,
'comments_count': comments_count,
'message': message,
}
return render(request, 'blog/posts/post.html', c)
Then I tried to convert it to a class-based view using this:
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post.html'
context_object_name = 'post'
def get_context_data(self, **kwargs):
self.slug = get_object_or_404(Post, slug=self.kwargs['slug'])
p = Post.objects.filter(slug=self.slug).first()
if p.exists():
p = p[0]
else:
return HttpResponseRedirect('/blog/')
count_visits = None
unique_views = set()
if self.request.user.is_authenticated:
post_views = PostView.objects.filter(post=p)
count_visits = post_views.count()
for post_view in post_views:
unique_views.add(post_view.ip)
else:
post_view = PostView(ip=self.request.META.get('REMOTE_ADDR', ''),
http_host=self.request.META.get('HTTP_HOST', ''),
http_referrer=self.request.META.get('HTTP_REFERER', ''),
http_user_agent=self.request.META.get('HTTP_USER_AGENT', ''),
remote_host=self.request.META.get('REMOTE_HOST', ''))
post_view.save()
c = {
'count_visits': count_visits,
'unique_views': unique_views,
}
return render(self.request, self.template_name, c)
I'm not sure this is the right way to go about this. Kindly assist me.
Many thanks.
A DetailView , by default, should take care of the pk/slug passed on onto your url, therefore you don't need to do the queryset your doing on the first 2 lines inside your get_context_data
. A believe a clearer way of doing that would look something like this:
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post.html'
context_object_name = 'post'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.object is None:
return HttpResponseRedirect(reverse('blog'))
count_visits = None
unique_views = set()
if self.request.user.is_authenticated:
post_views = PostView.objects.filter(post=self.object)
count_visits = post_views.count()
for post_view in post_views:
unique_views.add(post_view.ip)
else:
post_view = PostView.objects.create(
ip=self.request.META.get('REMOTE_ADDR', ''),
http_host=self.request.META.get('HTTP_HOST', ''),
http_referrer=self.request.META.get('HTTP_REFERER', ''),
http_user_agent=self.request.META.get('HTTP_USER_AGENT', ''),
remote_host=self.request.META.get('REMOTE_HOST', '')
)
context.update({
'count_visits': count_visits,
'unique_views': unique_views,
})
return context
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.