Django QuerySet object has no attribute 'objects - python

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.

Related

Using prefetch_related on category, subcategory and features

I'm trying to loop over my FeatureCatergories, FeatureSubcategories and Features. I'm able to loop over my feature categories just fine. Now I want to loop over my feature subcategories and finally features. I'm not sure what to call in my template for subcategories.. Should it be {{featuresubcategory.title}}? What about features?
views.py
def features_view(request):
context = {
"feature_categories": FeatureCategory.objects.prefetch_related('featuresubcategory_set').all(),
}
return render(request=request, template_name="main/features.html", context=context)
template.html
{% for category in feature_categories %}
{{category.title}}
{% for subcategory in featuresubcategory %}
{{ subcategory.title }}
{% endfor %}
{% endfor %}
models.py
class FeatureCategory(models.Model):
title = models.CharField(max_length=50)
featured_image = models.ImageField(blank=True, upload_to="features/")
category_slug = AutoSlugField(null=True, default=None,
unique=True, populate_from='title')
class Meta:
verbose_name_plural = "Feature Categories"
def __str__(self):
return self.title
class FeatureSubcategory(models.Model):
title = models.CharField(max_length=50)
category = models.ForeignKey('FeatureCategory', on_delete=models.CASCADE)
category_slug = AutoSlugField(null=True, default=None,
unique=True, populate_from='title')
class Meta:
verbose_name_plural = "Feature Subcategories"
def __str__(self):
return self.title
class Feature(models.Model):
title = models.CharField(max_length=150)
category = models.ManyToManyField(FeatureSubcategory)
description = models.TextField()
featured_image = models.ImageField(upload_to=image_dir)
class Meta:
verbose_name_plural = "Features"
def __str__(self):
return self.title
In your template, you must change
featuresubcategory with category.featuresubcategory_set.all()
also,
use prefetch_related('featuresubcategory') instead of prefetch_related('featuresubcategory_set')
{% for category in feature_categories %}
{{category.title}}
{% for subcategory in category.featuresubcategory_set.all %}
{{ subcategory.title }}
{% endfor %}
{% endfor %}
For features of subcategory, add related_name to your category field
category = models.ManyToManyField(FeatureSubcategory,related_name='subcategory_features')
and now, you can use it in your template, and don't forget to make migrate
{% for category in feature_categories %}
{{category.title}}
{% for subcategory in category.featuresubcategory_set.all %}
{{ subcategory.title }}
{% for feature in subcategory.subcategory_features.all %}
{{feature.title}}
{% endfor %}
{% endfor %}
{% endfor %}
You can see related objects reference here

how to get unique values in django

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

account/list_of_post_by_subactegory.html TemplateDoesNotExist

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

Django: List Products of each Categories in a page

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 %}

Django NoReverMatch at /

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.

Categories