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]
)
Related
There is a code in html {{post.author.posts.count}} that counts the number of posts by the author.
I have such a question, how to transfer it to views.py
def post_detail(request, post_id):
post = get_object_or_404(Post, id=post_id)
context = {
'post': post,
}
return render(request, 'posts/post_detail.html', context)
class model
class Post(models.Model):
text = models.TextField(verbose_name='Текст')
pub_date = models.DateTimeField(
auto_now_add=True,
verbose_name='Дата публикации'
)
group = models.ForeignKey(
Group,
on_delete=models.SET_NULL,
blank=True,
null=True,
related_name='posts',
verbose_name='Группа',
)
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='posts',
verbose_name='Автор',
)
def __str__(self):
return self.text
I need to find an existing post, find its author and sort all posts by this author and calculate the total number of posts
You can not pass values form HTML to views in Django, but you can create #property to count all posts of the specific author.
you can try like this
models.py
class Post(models.Model):
text = models.TextField(verbose_name='Текст')
pub_date = models.DateTimeField(
auto_now_add=True,
verbose_name='Дата публикации'
)
group = models.ForeignKey(
Group,
on_delete=models.SET_NULL,
blank=True,
null=True,
related_name='posts',
verbose_name='Группа',
)
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='posts',
verbose_name='Автор',
)
def __str__(self):
return self.text
views.py
def Demoview(request,post_id):
get_post = Post.object.get(id=post_id)
author_of_post = get_post.author
all_post_of_author= Post.object.filter(author__id=get_blog.author.id)
count_all_post_of_author= Post.object.filter(author__id=get_blog.author.id).count()
context = {
'author_of_post':author_of_post,
'all_post_of_author':all_post_of_author,
'count_all_post_of_author':count_all_post_of_author,
}
return render(request,'post.html',context)
Happened. Here is the code that came out.
def post_detail(request, post_id):
post = get_object_or_404(Post, id=post_id)
author = post.author
post_count = Post.objects.filter(author=author).count()
context = {
'author': author,
'post_count': post_count,
'post': post,
}
return render(request, 'posts/post_detail.html', context)
I had a question. I am creating an ecommerce website in django. There, I have categories and subcategories. When I enter to subcategory page, I able to render all products that relate to this subcategory. But, when I wanted to render all product that relate on one parent category, I am having troubles. So, I have some subcategories in one category. In that category page, I want to render all products that relate to one of subcategories of this category. Can you help me please?
models.py
class Category(models.Model):
parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, blank=True, null=True)
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
ordering = models.IntegerField(default=0)
is_featured = models.BooleanField(default=False)
class Meta:
verbose_name_plural = 'Categories'
ordering = ('ordering',)
def __str__(self):
if self.parent is not None:
return f"{self.parent}/{self.title}"
return self.title
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
def get_absolute_url(self):
return '/%s/' % (self.slug)
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
parent = models.ForeignKey('self', related_name='variants', on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=200, verbose_name="Название продукта")
price = models.IntegerField(verbose_name="Цена")
slug = models.SlugField(max_length=255)
description = models.CharField(max_length=5000,blank=True, verbose_name="Описание:")
image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
novinki = models.BooleanField(default=False, verbose_name="Новинки")
popularnye = models.BooleanField(default=False, verbose_name="Популарные")
def __str__(self):
return self.name
class Meta:
verbose_name = 'Продукты'
verbose_name_plural = "Продукты"
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
views.py
def category_detail(request, slug):
data = cartData(request)
cartItems = data['cartItems']
order = data['order']
items = data['items']
categories_for_menu = Category.objects.filter(parent=None)[:3]
categories = Category.objects.filter(parent=None)
category = get_object_or_404(Category, slug=slug)
**products_all = Product.objects.filter(category.parent==category)**
print(products_all)
products = category.products.all()
context = {'items' : items, 'order' : order, 'cartItems' : cartItems, 'products':products, 'category':category, 'categories':categories,'categories_for_menu':categories_for_menu,'products_all':products_all}
return render(request, "store/categories.html", context)
Here I want to save all products that relate the category in products_all. Looking forward to your help!
class Category(models.Model):
# ...
root = models.ForeignKey('self', on_delete=models.CASCADE)
# ...
def save(self, *args, **kwargs):
self.root = self.parent.root if self.parent else self
# I didn't debug it. Maybe it has some bug.
super(Category, self).save(*args, **kwargs)
# query
Product.objects.filter(category__root=(...))
I don't agree this answer:
products = Product.objects.filter(Q(category = category)|Q(category__parent = category))
When your category is more than 2 depth, it will be wrong.
You can do it using Q function:
from django.db.models import Q
category = get_object_or_404(Category, slug=slug)
products = Product.objects.filter(Q(category = category)|Q(category__parent = category))
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
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.
enter image description here
I see URL, but click on it not goving at page.
If I go directly to the link, the page opens. In my opinion the matter lies in the def post_list
model
class Category(models.Model):
name = models.CharField(max_length=128, unique=True, verbose_name='Название')
slug = models.SlugField(unique=True)
image = models.ImageField(null=True, blank=True, verbose_name='Изображение')
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
class Meta:
verbose_name = 'Категории'
verbose_name_plural = 'Категории'
def __str__(self): # For Python 2, use __unicode__ too
return self.name
def get_absolute_url(self):
return reverse('show_category', kwargs={'slug': self.slug})
class Post(models.Model):
category = models.ForeignKey(Category, default=1, verbose_name='Категория')
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, verbose_name='Пользователь')
title = models.CharField(max_length=120, verbose_name='Заголовок')
slug = models.SlugField(unique=True)
image = models.ImageField(null=True, blank=True, verbose_name='Изображение')
content = models.TextField(max_length=10000, verbose_name='Контент')
updated = models.DateTimeField(auto_now=True, auto_now_add=False, verbose_name='Обновлено')
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True, verbose_name='Создано')
keywords = models.CharField(max_length=1024, blank=True, null=True)
description = models.CharField(max_length=1024, blank=True, null=True)
class Meta:
verbose_name = 'Статьи'
verbose_name_plural = 'Статьи'
ordering = ["-timestamp", "-updated"]
def __str__(self): # For Python 2, use __unicode__ too
return self.title
def get_absolute_url(self):
return reverse('detail', kwargs={'slug': self.slug, 'category': self.category})
views
only problem page
def post_list(request):
queryset_list = Post.objects.all()
category_list = Category.objects.all()
search = request.GET.get("s")
if search:
queryset_list = queryset_list.filter(
Q(title__icontains=search) |
Q(content__icontains=search) #|
#Q(user__first_name__icontains=search) |
#Q(user__last_name__icontains=search)
).distinct()
paginator = Paginator(queryset_list, 5) # Show 5 contacts per page
page = request.GET.get('page')
try:
queryset = paginator.page(page)
except PageNotAnInteger:
queryset = paginator.page(1)
except EmptyPage:
queryset = paginator.page(paginator.num_pages)
context = {
"object_list": queryset,
"category_list": category_list,
"title": "Новое"
}
return render(request, "post_list.html", context)
urls
from .views import (
post_list,
post_detail,
show_category,
)
urlpatterns = [
url(r'^$', post_list, name="list"),
url(r'^(?P<category>[-\w]+)/(?P<slug>[-\w]+)/$', post_detail, name="detail"),
url(r'^(?P<slug>[-\w]+)/$', show_category, name='show_category'),
]
html
{% for cat in category_list %}
<li>{{ cat.name }}</li>
{% endfor %}