I can't solve this problem. When you try to load the page, list_of_post_by_subcategory.html throws TemplatesDoesNotExist, Please help.
models.py
class Category(models.Model):
category = models.CharField(max_length=250)
slug = models.SlugField()
def __str__(self):
return self.category
def get_absolute_url(self):
return reverse('list_of_post_by_category', args=[self.slug])
class SubCategory(models.Model):
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True, related_name="subcategories")
subcategory = models.CharField(max_length=250)
slug = models.SlugField()
def __str__(self):
return self.subcategory
def get_absolute_url(self):
return reverse('list_of_post_by_subcategory', args=[self.slug])
urls.py
url(r'^category/(?P<slug>[-\w]+)/$', views.list_of_post_by_category, name= 'list_of_post_by_category'),
url(r'^subcategory/(?P<slug>[-\w]+)/$', views.list_of_post_by_subcategory, name= 'list_of_post_by_subcategory'),
views.py
def list_of_post_by_category(request, slug):
categories = Category.objects.all()
category=get_object_or_404(Category, slug = slug)
subcategories = SubCategory.objects.filter(category=category)
posts = Post.objects.filter(category=category)
return render(request, "account/list_of_post_by_category.html", {'categories': categories, 'posts': posts, 'category': category, 'subcategories': subcategories})
def list_of_post_by_subcategory(request, slug):
subcategory=get_object_or_404(SubCategory, slug=slug)
posts = Post.objects.filter(subcategory=subcategory)
return render(request, "account/list_of_post_by_subcategory.html", {'posts': posts, 'subcategory': subcategory})
list_of_post_by_subcategory.html
{% extends "base.html" %}
{% block title %}{{ subcategory.subcategory }}{% endblock %}
{% block content %}
<h1>{{ subcategory.subcategory }}</h1>
{% for post in posts %}
<div class="single_post">
{{ post.title }}
<br/>
<br/>
<div>
{{ post.publish }}
{{ post.subcategory }}
</div>
</div>
{% endfor %}
<br/>
{% endblock %}
Similar template list_of_post_by_category.html loads correctly. But list_of_post_by_subcategory.html throws TemplateDoesNotExist.
The filenames don't match here. You posted your error as account/list_of_post_by_subactegory.html TemplateDoesNotExist Look at the name of html file you mentioned(subactegory). And the one you are calling has this name account/list_of_post_by_subcategory.html
Related
I want to show my articles but
My article doesn't display on article_details.html
This is what my site looks like. You can see only my article's title works.
My models.py:
class Article(models.Model):
title = models.CharField(max_length=50, verbose_name="Title")
mini_description = models.TextField(max_length=100, default='', verbose_name='Mini_description')
content = models.TextField(blank=True, verbose_name="Content")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Date of add")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Update date")
photo = models.ImageField(upload_to='photos/', verbose_name="Photo")
is_published = models.BooleanField(default=True, verbose_name="Is published")
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name="Category")
def get_absolute_url(self):
return reverse("article_details", kwargs={'pk': self.pk})
def __str__(self):
return self.title
def __repr__(self):
return f"Article(pk={self.pk}, title='{self.title}')"
class Meta:
verbose_name = "Article"
verbose_name_plural = "Articles"
ordering = ['-created_at']
My views.py:
class ArticleListByCategory(ListView):
model = Article
context_object_name = 'articles'
template_name = 'blog/details.html'
def get_queryset(self):
sort_filed = self.request.GET.get('sorter')
articles = Article.objects.filter(category_id=self.kwargs['pk'])
if sort_filed:
articles = articles.order_by(sort_filed)
return articles
class ArticleDetails(ArticleListByCategory):
model = Article
context_object_name = 'article'
template_name = 'blog/article_details.html'
def get_queryset(self):
article = Article.objects.filter(pk=self.kwargs['pk'], is_published=True).select_related('category')
return article
def get_context_data(self, **kwargs):
context = super().get_context_data()
article = Article.objects.get(pk=self.kwargs['pk'])
context['title'] = f"Article: {article.title}"
return context
My article_details.html:
{% extends "base.html" %}
{% load static %}
{% block style %}
<link href="{% static 'blog/css/main.css' %}" rel="stylesheet">
{% endblock style %}
{% block title %}
{{ title }}
{% endblock %}
{% block main %}
<section class="articles" id="articles">
<div class="card_details">
<h1>{{ article.title }}</h1>
<p><em>{{ article.mini_description }}
</em>
</p>
<img src="">
<div class="description">
<p>
{{ article.content }}
</p>
</div>
<div class="card-footer text-muted">
{{ article.created_at| timesince }} ago
</div>
</div>
</section>
{% endblock main %}
I don't know why my article doesn't display.
What I'd suggest here is using the Django Generic View called DetailView. For example, you could do the following:
from django.views.generic import DetailView
class ArticleDetails(DetailView):
context_object_name = 'article'
template_name = 'blog/article_details.html'
# Using the get_object method here, not get_queryset.
def get_object(self, queryset=None):
article = Article.objects.filter(pk=self.kwargs['pk'], is_published=True).select_related('category')
return article
Ideally, that should work.
I have a category model and list of posts related to those category also some post with same category name but when i wanted to make list of category section in template,
it showing duplicate name of category as it related to posts like:
food,
food,
desert,
style,
desert,
but I want like:
food,
desert,
style,
here is my code:
views.py
class ListCategory(ListView):
model = Post
paginate_by = 2
template_name = 'shit.html'
context_object_name = 'queryset'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
cate = Post.objects.all()
context['cate'] = cate
return context
models.py
class Category(models.Model):
title = models.CharField(max_length=20)
thumbnail = models.ImageField()
detail = models.TextField()
featured = models.BooleanField(default=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-category', kwargs={
'pk': self.pk
})
class Post(models.Model):
title = models.CharField(max_length=100)
overview = models.TextField()
featured = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(Author,on_delete=models.CASCADE)
thumbnail = models.ImageField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
tags = TaggableManager()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={
'pk': self.pk
})
templates
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="sidebar-box ftco-animate">
<ul class="categories">
<h3 class="heading mb-4">Categories</h3>
{% for cat in cate %}
<li>{{cat.category}}<span>(12)</span></li>
{% endfor %}
</ul>
</div>
{% endblock content %}
Thank you so much!
Seems like you want to group your Posts, based on their category; so you can achieve that by iterating over the Category (instead of Post), and use the backward relationship to find out the related Post objects.
views.py
class ListCategory(ListView):
model = Category
paginate_by = 2
template_name = 'shit.html' # :)
context_object_name = 'queryset'
template:
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="sidebar-box ftco-animate">
<ul class="categories">
<h3 class="heading mb-4">Categories</h3>
{% for category in queryset %}
<li>{{category}}<span>{{ category.posts_set.count }}</span></li>
<ul>
{% for post in category.post_set.all %}
<li>{{ post }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
</div>
{% endblock content %}
I also use {{ category.post_set.count }} instead of 12, since I think you are looking for the number of Post objects within each category.
You can use unique=True in desired field, to make every value unique. If you'll try to add new record with same value of unique field, a django.db.IntegrityError will be raised.
More about unique
More about model's fields options
I have a few categories and I would like to list the products per category in the format below (categories is an FK to products):
Category 1
bunch of products
....
Category N
bunch of products
I have tried many ways but so far I only get the categories but not the products to show in my HTML.
models.py
class Category(models.Model):
title = models.CharField(max_length=225)
slug = models.SlugField(unique=True, blank=True, null=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('category_detail', kwargs={'slug': self.slug})
#property
def get_products(self):
return Products.objects.filter(category=self.title)
class Products(models.Model):
title = models.CharField(max_length=225)
image = models.ImageField(upload_to=upload_image_path, null=True, blank=True)
blank=True, on_delete=models.CASCADE)
categories = models.ForeignKey(Category, related_name='Category', blank=True, on_delete=models.CASCADE) #this
gender = models.CharField(max_length=20, choices=GENDER_CHOICES, default="male")
objects = ProductManager()
def get_absolute_url(self):
return reverse('product_detail', args=(self.id,))
def __str__(self):
return self.title
views.py
def categories_m(request):
query_Set = models.Category.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(query_Set, 20)
try:
cat = paginator.page(page)
except PageNotAnInteger:
cat = paginator.page(1)
except EmptyPage:
cat = paginator.page(paginator.num_pages)
return render(request, 'products/categories.html', {'categories': cat})
html
{% extends 'base.html' %}
{% block content %}
{% for category in categories %}
<h1>{{ category }}</h1>
{% for product in categories.get_products %}
<p>{{ product }}</p>
{% endfor %}
{% endfor %}
{% endblock %}
It should be category instead of categories in your template. And in your model filter products by category title.
#property
def get_products(self):
return Products.objects.filter(categories__title=self.title)
{% extends 'base.html' %}
{% block content %}
{% for category in categories %}
<h1> {{category}} </h1>
{% for product in category.get_products %}
<p> {{product}} </p>
{% endfor %}
{% endfor %}
{% endblock %}
You could remove the related_name attribute from your field
class Products(models.Model):
categories = models.ForeignKey(Category, blank=True, on_delete=models.CASCADE)
And then in your template you can use category.products_set.all
{% extends 'base.html' %}
{% block content %}
{% for category in categories %}
<h1>{{ category }}</h1>
{% for product in category.products_set.all %}
<p>{{ product }}</p>
{% endfor %}
{% endfor %}
{% endblock %}
I have problem with show product in category. (Products are show but when i click on category (tshirt) i have this problem AttributeError at /man/tshirt/
'QuerySet' object has no attribute 'objects
views.py
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(section='man', available=True)
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
products = products.objects.filter(category=category)
return render(request,
'shop/product/list.html',
{'category': category,
'categories': categories,
'products': products})
urls.py
urlpatterns = [
url(r'^$', views.main, name='main'),
url(r'^man/$', views.product_list, name='product_list'),
url(r'^man/(?P<category_slug>[-\w]+)/$',
views.product_list,
name='product_list_by_category'),
]
models.py
class Category(models.Model):
name = models.CharField(max_length=200,
db_index=True)
slug = models.SlugField(max_length=200,
db_index=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('shop:product_list_by_category',
args=[self.slug])
list.html
{% extends "shop/base.html" %}
{% load static %}
{% block title %}VPW{% endblock %}
{% block content %}
<ul>
{% for c in categories %}
<li>
{{c.name}}
</li>
{% endfor %}
</ul>
{% for product in products %}
{{ product.name }}
{% endfor %}
{% endblock %}
You should change
products = products.objects.filter(category=category)
to
products = products.filter(category=category)
In short, you've already queried data at the objects level, thus the .objects identifier is no longer necessary or valid at this point in the code.
You can find more info here.
I read the book 'Django By Example' and run the examples in chaper7.
But the results call "NoReverMatch at /"
NoReverseMatch at /
Reverse for 'product_detail' with arguments '(5, u'ironman')' and keyword arguments '{}' not found. 1 pattern(s) tried: ['(?P<id>[\\d+])/(?P<slug>[-\\w+])/$']
This is the models.py
class Category(models.Model):
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('shop:product_list_by_category', args=[self.slug])
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products')
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True)
image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.PositiveIntegerField()
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('-created',)
index_together = (('id', 'slug'),)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('shop:product_detail', args=[self.id, self.slug])
This is the urls.py
urlpatterns = [
url(r'^$', views.product_list, name='product_list'),
url(r'^(?P<category_slug>[-\w]+)/$', views.product_list, name='product_list_by_category'),
url(r'^(?P<id>\d+)/(?P<slug>[-\w+])/$', views.product_detail, name='product_detail'),
]
This is the views.py
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
products = products.filter(category=category)
return render(request, 'shop/product/list.html', {'category': category, 'categories': categories, 'products': products})
def product_detail(request, id, slug):
product = get_object_or_404(Product,
id=id,
slug=slug,
available=True)
return render(request, 'shop/product/detail.html', {'product': product})
And this is the 'list.html' template where the error occurs.
{% extends "shop/base.html" %}
{% load static %}
{% block title %}
{% if category %}{{ category.name }}{% else %}Products{% endif %}
{% endblock %}
{% block content %}
<div id="sidebar">
<h3>Categories</h3>
<ul>
<li {% if not category %} class="selected" {% endif %}>
All
</li>
{% for c in categories %}
<li {% if category.slug == c.slug %} class="selected" {% endif %}>
{{ c.name }}
</li>
{% endfor %}
</ul>
</div>
<div id="main" class="product-list">
<h1>{% if category %}{{ category.name }}{% else %}Products{% endif %} </h1>
{% for product in products %}
<div class="item">
<a href="{{ product.get_absolute_url }}">
<img src="{% if product.image %}{{ product.image.url }}{% else %}{% static 'img/no_image.png' %}{% endif %}">
</a>
{{ product.name }}<br>
${{ product.price }}
</div>
{% endfor %}
</div>
{% endblock %}
The error occurs at
<a href="{{ product.get_absolute_url }}">
-- line.
Why this error occurs??
It looks to me like you need to change your url pattern:
url(r'^(?P<id>\d+)/(?P<slug>[-\w+])/$', views.product_detail, name='product_detail')
perhaps to:
url(r'^(?P<id>\d+)/(?P<slug>[-\w]+)/$', views.product_detail, name='product_detail')
'+' does not function as a special character inside square brackets, so [-\w+] will only match a single character (alphanumeric or '-'), but you are passing multi-character strings like 'ironman'. [-\w]+ will match one or more characters.