How to call ManyToManyField in class based view - django

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

Related

How can I filter This in django?

I am working on a Django project (like LMS) and I want to filter Lectures by Subject in the template, I do it once but now I forgot how to do it. How can I do this?!
I want to filter it by foreign-key Subject in Lecture
Here is my models.py
from django.db import models
from django.utils.text import slugify
# Create your models here.
class Subject(models.Model):
Title = models.CharField(max_length=150)
Pic = models.ImageField(upload_to='media/')
Test = models.CharField(max_length=300, null=True, blank=True)
Slug = models.SlugField(unique=True, null=True, blank=True)
def save(self, *args, **kwargs):
self.Slug = slugify(self.Title, allow_unicode=True)
super(Subject, self).save(*args, **kwargs)
def __str__(self):
return self.Title
class Lecture(models.Model):
Subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
Title = models.CharField(max_length=150)
Video = models.CharField(max_length=300)
More_Info = models.TextField()
Audio_Lecture = models.CharField(max_length=300)
Lecture_Files = models.CharField(max_length=300)
Sheet = models.CharField(max_length=300)
Slug = models.SlugField(unique=True, null=True, blank=True)
def save(self, *args, **kwargs):
self.Slug = slugify(self.Title, allow_unicode=True)
super(Lecture, self).save(*args, **kwargs)
def __str__(self):
return self.Title
and here is my views.py
from Diploma.models import Lecture, Subject
from django.shortcuts import render
# Create your views here.
def Diploma(request):
return render(request, 'Diploma/diploma.html', context={
'sub' : Subject.objects.all(),
})
def Diploma_Subject(request, slug):
subject_Lecture = Subject.objects.all()
return render(request, 'Diploma/subject.html', context={
'subj' : subject_Lecture,
'lect' : Lecture.objects.filter(I do not know what I should write here)
})
If you want to filter the Lecture model based on the slug parameter you have to do the following:
lecture = Lecture.objects.filter(Slug=slug).first()
if lecture is not None:
# lecture.Subject, lecture.Title ...
Or if you want to filter based on the slug property in Subject model you can do the following:
lectures = Lecture.objects.filter(Subject__Slug=slug)
for lecture in lectures:
# lecture.Subject, lecture.Title ...
empty:
print('There are any lectures related')
There are many things to explain here but I tried to give you a minimal repoducible example so you can custom it to achieve your goal.
Feel free to leave a comment if you have an specific doubt about understanding it.

Not Found: /post/12/responses/

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.

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.

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.

get attribute name based on slug

I have a page listing articles based on categories.
The category is filtered from the slug in the url.
I want to display a tag in the template with the category name.
With get_context_data I am able to retrive the slug and use it as {{categoryslug}} But how do I get the name of the category given the slug?
Model.py
class Category(models.Model):
name = models.CharField(max_length=50,unique=True, blank=True)
slug = models.SlugField(max_length=100,unique=True, blank=True)
def __str__(self):
return self.name
class Article(models.Model):
title= models.CharField(max_length=40, blank=True)
category = models.ForeignKey('Category', on_delete= models.PROTECT, related_name="pcat", blank=True)
def __str__(self):
return self.title
View.py
class ListArticleView(ListView):
model = Article
context_object_name = "listcat"
template_name = "myapp/categories.html"
paginate_by = 5
def get_queryset(self):
return Article.objects.filter(category__slug=self.kwargs['cat_slug'])
def get_context_data(self, **kwargs):
context=super(ListArticleView,self).get_context_data(**kwargs)
context['categoryslug']=self.kwargs['cat_slug']
return context
URLS.py
path(('/<cat_slug>'), views.ListArticleView.as_view(), name='some_categories'))