So as the title says, i need to get the current post's category to use it in a "related posts" section, more precisely what to put in cat_posts = Post.objects.filter(Category=????)
(don't mind the comments variable since i removed part of my PostView from this post)
here's my code
views.py
def PostView(request, slug):
template_name = 'post-page.html'
post = get_object_or_404(Post, slug=slug)
comments = post.comments.filter(active=True)
cat_posts = Post.objects.filter(Category=Post.Category)
cat_posts = cat_posts.order_by('-Date')[:3}
return render(request, template_name, {'post': post,
'cat_posts':cat_posts})
models.py
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return str(self.name)
class Post(models.Model):
title = models.CharField(max_length=120)
Category = models.CharField(max_length=120, default='None')
Thumbnail = models.ImageField(null=True, blank=True, upload_to="images/")
Text = RichTextField(blank=False, null=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
Overview = models.CharField(max_length=400)
Date = models.DateTimeField(auto_now_add=True)
main_story = models.BooleanField(default=False)
def __str__(self):
return str(self.title)
def get_absolute_url(self):
# return reverse('about', args=(str(self.id)))
return reverse('home')
You can obtain this with the post.Category (so the post *object, not the Post class):
def PostView(request, slug):
template_name = 'post-page.html'
post = get_object_or_404(Post, slug=slug)
comments = post.comments.filter(active=True)
cat_posts = Post.objects.filter(
Category=post.Category
).order_by('-Date')[:3]
return render(
request,
template_name,
{'post': post, 'cat_posts':cat_posts}
)
It is however better to work with a ForeignKey [Django-doc] to the Category than a CharField: if you later change the name of the category, then your posts are no longer pointing to a valid category.
Note: normally the name of the fields in a Django model are written in snake_case, not PerlCase, so it should be: category instead of Category.
Related
I have a BlogPage that references all my blogs with snippets of text. These can be clicked to view the full blog on a ViewBlog page, at the bottom of the view-blog page you can add a comment, and all comments are subsequently shown on this page.
I want to be able to reference the amount of comments made on every post some where on the snippet box on the blog page as screenshot below shows (I don't require help with the code for this, only the code to be able to reference it on the BlogPage;
MODELS.PY
class BlogPost(models.Model):
title = models.CharField(max_length=100, null=False, blank=False, default="")
text = RichTextUploadingField(null=True, blank=True, default="text")
featured_text = models.TextField(max_length=550, null=True, blank=True, default="text")
image = models.ImageField(null=True, blank=True, upload_to="images", default="default.png")
date = models.DateField(auto_now_add=True)
published = models.BooleanField(default=False)
featured = models.BooleanField(default=False)
slug = models.SlugField()
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.title)
super().save(*args, **kwargs)
def __str__(self):
return self.title
class BlogComment(models.Model):
post = models.ForeignKey(BlogPost, related_name="comments", on_delete=models.CASCADE)
name = models.CharField('Name',max_length=100, default="")
text = models.TextField('Comment',max_length=1000, default="")
date = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=True)
class Meta:
ordering = ("date",)
def __str__(self):
return '%s -- Name: %s'%(self.post.title, self.name)
VIEWS
def BlogPage(request):
posts = BlogPost.objects.filter(date__lte=timezone.now()).order_by('-date')
blog_paginator = Paginator(posts, per_page=4)
page_number = request.GET.get('page')
page = blog_paginator.get_page(page_number)
context = {'page': page}
return render(request, 'mhpapp/blog.html', context)
def ViewBlog(request, slug):
try:
blog = BlogPost.objects.get(slug=slug)
except BlogPost.DoesNotExist:
print("Blog with this slug does not exist")
blog = None
comments = blog.comments.filter(status=True)
user_comment = None
if request.method == 'POST':
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
user_comment.post = blog
user_comment.save()
else:
comment_form = CommentForm()
return render(request, 'mhpapp/view-blog.html', {'blog': blog, 'slug': slug, 'comments': user_comment, 'comments': comments, 'comment_form': comment_form})
You can use the reverse relation from Comment to Blog like blog.comments.all().count() will return all comments related to a blog. You could probably use a method on your Blog model:
#property
def comment_count(self):
return blog.comments.all().count()
And in your template you can then use this property to show the amount of comments.
What I am trying to do is to get particular post comments.
models.py
class Post(models.Model):
title = models.CharField(max_length = 100)
content = models.TextField()
date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Comments(models.Model):
post = models.ForeignKey(Post,related_name='comments',on_delete=models.CASCADE)
name = models.CharField(max_length=50)
date = models.DateTimeField(default=timezone.now)
content = models.TextField()
def get_absolute_url(self):
return reverse('Home')
views.py
class CommentDetailView(DetailView):
model = Comments
template_name = 'CovidHelp/comment_response.html'
context_object_name = 'comments'
paginate_by = 10
def get_queryset(self):
post = get_object_or_404(Post, id=self.kwargs.get('pk'))
return Comments.objects.filter(post=post).order_by('-date')
urls.py
path('post/<int:pk>/responses/', CommentDetailView.as_view(), name='responses')
However I'm getting error when trying to access such an url:
Not Found: /post/12/responses/
you want to return a list of comments for a post right?
so you need to use Listview instead of using detailview to return a list of comments and then use get_queryset to filter it by the post id.
Hi i have a problem with comments on my Blog app in Django.
Everything is working fine except that i want to display comment sorted by date (newest on top)
o and it'll be great i'll be able to put in to the author field user that is actually loged in.. TY
views.py
#login_required
def add_comment_to_post(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('post-detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/add_comment_to_post.html', {'form': form})
models.py
class Comment(models.Model):
post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='comments')
author = models.CharField(max_length=100)
text = models.TextField()
created_on = models.DateTimeField(default=timezone.now)
active = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def __str__(self):
return self.text
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text', 'created_on')
one option is, in your models add a meta class as follows
class Meta:
ordering = ['-created_on']
Add class Meta: ordering(-date_posted), date_posted can be changed to the variable containing the DateTimeField()
class BlogComment(models.Model):
blogpost_connected = models.ForeignKey(Posts, related_name='comments', on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.CharField(max_length=255, null=True)
date_posted = models.DateTimeField(default=timezone.now)
class Meta:
ordering = ['-date_posted']
def __str__(self):
return str(self.author) + ', ' + self.blogpost_connected.title[:40]
I'm trying to display a blog as follows:
domain.com/blog/category/categoryA
domain.com/blog/category/categoryA/post-one
At the moment (1) works successfully, and (2) works partially, so it displays like:
domain.com/blog/post-one
How can I set post category - posts that belong to that category before display post slug?
My urls.py:
url(r'^(?P<slug>[-\w]+)/$', views.post_detail, name='post_detail'),
url(r'^category/(?P<category_slug>[-\w]+)/$', views.list_of_post_by_category, name='list_of_post_by_category'),
My views.py
def list_of_post_by_category(request,category_slug):
categories = Category.objects.all()
post = Post.objects.filter(status='published')
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
post = post.filter(category=category)
template = 'blog/category/list_of_post_by_category.html'
context = {'categories': categories, 'post': post}
return render(request, template, context)
def list_of_post(request):
post = Post.objects.filter(status="published")
template = 'blog/post/list_of_post.html'
context = {'post': post}
return render(request, template, context)
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
template = 'blog/post/post_detail.html'
context = {'post': post}
return render(request, template, context)
My models.py:
class Category(models.Model):
name = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def get_absoulte_url(self):
return reverse('blogCMSApp:list_of_post_by_category', args=[self.slug])
def __str__(self):
return self.name
# Posts
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published')
)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique=True)
content = models.TextField()
seo_title = models.CharField(max_length=250)
seo_description = models.CharField(max_length=160)
author = models.ForeignKey(User, related_name='blog_posts', on_delete=models.PROTECT)
published = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=9, choices=STATUS_CHOICES, default='draft')
def get_absoulte_url(self):
return reverse('blogCMSApp:post_detail', args=[self.slug])
def __str__(self):
return self.title
You need to look for that pattern in urls.py, and then you need to build the correct URL for the post links:
url(
r'^category/(?P<category_slug>[-\w]+)/(?P<slug>[-\w]+)/$',
views.post_detail,
name='post_detail'
),
url(
r'^category/(?P<category_slug>[-\w]+)/$',
views.list_of_post_by_category,
name='list_of_post_by_category'
),
And in the Post model:
def get_absoulte_url(self):
return reverse(
'blogCMSApp:post_detail',
args=[self.category.slug, self.slug]
)
I'm just bricked here; I don’t know what is going on?
I want to do simple blog.
So as you can see below I defined ManyToManyField and set category as a many to many field and then related the name posts.
Earlier I used a function based view and I simply called it a related name like this:
example
def catdetail(request, slug):
code here
and
posts = category.pots.all() /////and this gave me all posts related to this cateogry,
But in the class based view in the category detail view I cannot call this category field from Post; all my tries are unsuccessful; errors like, category has not defined, category has no object, category or post and thing similar to that which you already know…
So my question is: how can I call this related name in Detail view in category?
Here are my models and views.py:
class Category(models.Model):
title = models.CharField(max_length=20)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse("category_detail", kwargs={"slug": self.slug})
class Tag(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.title
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
category = models.ManyToManyField(Category, related_name='posts')
title = models.CharField(max_length=100, blank=False)
slug = models.SlugField(unique=True)
body = models.TextField()
image = models.ImageField(upload_to='project/uploads/')
tag = models.ManyToManyField(Tag, related_name='tag_post')
date = models.DateTimeField(auto_now_add=True, auto_now=False)
date_mod = models.DateTimeField(auto_now=True, auto_now_add=False)
publis = models.BooleanField(default=True)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse("post_detail", kwargs={"slug": self.slug})
and views.py.
Can you tell me how to call the category field and related name here in views?
class CategoryDetail(DetailView):
model = Category
template_name = "cat_detail.html"
def get_context_data(self, *args, **kwargs):
context = super(CategoryDetail, self).get_context_data(*args, **kwargs)
context['cat'] = get_object_or_404(Category, slug=self.kwargs.get("slug"))
return context
Some help?
def get_context_data(self, *args, **kwargs):
context = super(CategoryDetail, self).get_context_data(*args, **kwargs)
posts = Category.objects.get(id=1).posts.all()
for post in posts:
post.category
print post
context['cat'] = get_object_or_404(Category, slug=self.kwargs.get("slug"))
return context
i now have this, but i got all posts whether be on that category or not