Reference comment count on different using Django - django

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.

Related

Django Forms - how to add the + sign for a Many2Many field

enter image description hereRelated to Django Forms and Many2Many
I have tried to look for ways to add the + to my django form when I want to add a new post to my webpage.
What I'm looking for is a similar function as the one in admin module. See picture.
I have tried to read though the docs but not sure what to look for. Have anybody build something similar?
my model looks like this
class Wine_taste(models.Model):
title = models.CharField(max_length=128, null=True, blank=True)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
category = models.ManyToManyField('Wine_Category', verbose_name='Kind of Wine',related_name='wcategory')
subcategory = models.ForeignKey('Wine_SubCategory', verbose_name='Wine type',on_delete=models.SET_NULL, null=True, blank=True)
review = models.TextField()
producer_taste = models.ForeignKey('Wine_Producer', verbose_name='Producer or shipper', on_delete=models.SET_NULL, null=True, blank=True )
grape_taste = models.ManyToManyField('Wine_Grapes', verbose_name='Grapes')
country_taste = models.ForeignKey('Wine_Country', verbose_name='Country of origin', on_delete=models.SET_NULL, null=True, blank=True )
sweetness = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate Sweetness')
acid = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate acid level')
fruit = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate fruitness')
taste = models.PositiveSmallIntegerField(choices=RATE_CHOICES, verbose_name='Rate taste')
overall = models.PositiveSmallIntegerField(choices=RATE_CHOICES, verbose_name='Overall rate')
thumbnail = models.ImageField()
timestamp = models.DateTimeField(auto_now_add=True)
featured = models.BooleanField()
previous_post = models.ForeignKey('self', related_name='previous', on_delete=models.SET_NULL, null=True, blank=True)
next_post = models.ForeignKey('self', related_name='next', on_delete=models.SET_NULL, null=True, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('wine:wine-dyn', kwargs={"id": self.id})
def get_update_url(self):
return reverse('wine:wine-update', kwargs={"id": self.id})
def get_delete_url(self):
return reverse('wine:wine-delete', kwargs={"id": self.id})
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.thumbnail.path)
if img.height > 400:
new_height = 400
new_width = new_height / img.height * img.width
output_size = ((new_height, new_width))
img.thumbnail(output_size)
img.save(self.thumbnail.path)
#property
def get_comments(self):
return self.comments.all().order_by('-timestamp')
#property
def comment_count(self):
return Comment.objects.filter(post=self).count()
#property
def view_count(self):
return PostView.objects.filter(post=self).count()
Blockquote
this is my view:
def wine_detailed_create(request):
title = 'Create'
form = CreateForm(request.POST or None, request.FILES or None)
author = get_author(request.user)
if request.method == 'POST':
if form.is_valid():
form.instance.author = author
form.save()
return redirect (reverse('wine:wine-dyn', kwargs={'id': form.instance.id}))
context = {
'title': title,
'form': form
}
return render(request, 'wine/wine_create.html', context)
and my forms:
class CreateForm(forms.ModelForm):
class Meta:
model = Wine_taste
fields = ('title',
'country_taste',
'category',
'subcategory',
'producer_taste',
'grape_taste',
'review',
'thumbnail',
'sweetness',
'acid',
'fruit',
'taste',
'overall',
'featured',
'previous_post',
'next_post',)
Blockquote
br
Lars

Get current post's category

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.

Sort Blog Post comments by date DJANGO

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]

How to delete object using function based view?

I am having trouble trying to implement a delete function-based view as I am unsure of what is the correct syntax.
So far this is the method that I am using:
def delete_lesson(request, post_id):
if request.method == 'POST':
lesson = Lesson.objects.get(post_id=request.get('post_id'))
lesson.delete()
return redirect('/')
I have implemented the delete function in my model:
class Lesson(models.Model):
title = models.CharField(max_length=100)
file = models.FileField(upload_to="lesson/pdf")
date_posted = models.DateTimeField(default=timezone.now)
post = models.ForeignKey(Post, on_delete=models.CASCADE, null=False, blank=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('lesson_upload', kwargs={'pk': self.pk})
def delete(self, *args, **kwargs):
self.file.delete()
self.title.delete()
super().delete(*args, **kwargs)
class Post(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(default = 'default0.jpg', upload_to='course_image/')
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=6)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
rating = models.IntegerField(default = 0)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk' : self.pk})
My urls.py:
path('post/<int:post_id>/lesson_delete/', views.delete_lesson, name='delete_lesson'),
You have a post_id in your URL which passes the id to your view which you also received.
So if you want to remove the post with the id in your URL then this is how you can do:
lesson = Lesson.objects.get(post_id=post_id)
If for any reasons you get a post id from your template and it's different than the post id in your URL, then this is how you should do it:
Lesson.objects.get(post_id=request.POST.get('post_id'))
Note if you're using the second option which the post_id you want to delete is different than what you have in post/<int:post_id>/lesson_delete/ then you should pass the post_id as a POST data from your template.

How to call ManyToManyField in class based view

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