I get this error:
ValueError at /product/
The QuerySet value for an exact lookup must be limited to one result using slicing.
this is my models :
class Categorie (models.Model):
title = models.CharField(max_length=50)
category_slug = models.SlugField(blank=True)
def __str__(self):
return self.category_slug
class Products(models.Model):
category = models.ForeignKey(Categorie,on_delete=models.CASCADE,null=True,
related_name="product")
product_slug = models.SlugField(blank=True)
product_title = models.CharField(max_length=50 , null=True)
product_name = models.CharField(max_length=100 , null=True )
product_describe = models.CharField(max_length=200 , null=True)
product_picture = models.ImageField(upload_to='img_pro' , null=True)
product_created_at = models.DateField(auto_now_add=True)
product_updated_at = models.DateField(auto_now=True)
def __str__(self):
return self.product_slug
this is my view:
def index(requset):
category = Categorie.objects.all()
product = Products.objects.filter(category_slug=category)
context = {
'category':category,
'product ':product ,
}
return render( requset , 'product/index.html' , context)
this is my template:
{% for cat in category %}
<div class="fix single_content">
<h2>{{cat.title}}</h2>
<div class="fix">
{% for pro in product %}
<ul>
<li>
<div class="entry_name"><a href=""><img src="{{pro.product_picture.url}}" alt=""><span>
{{pro.product_title}}</span></a><h6>{{pro.product_name}}</h6></div>
</li>
</ul>
{% endfor %}
</div>
{% endfor %}
this is myapp.urls:
from django.urls import path
from . import views
urlpatterns = [
path('' , views.index , name='index' ),
]
Can anyone help me with that please?
in you index view you are passing a everything you have in vategory
category = Categorie.objects.all()
while it is expecting just one thing
category = Categorie.objects.get(id=pk) # pk or category_id or slug or whatever you named it in your url
so your view should look like
def index(requset,pk):
category = Categorie.objects.get(id=pk)
product = Products.objects.filter(category=category)
context = {
'category':category,
'product ':product ,
}
return render( requset , 'product/index.html' , context)
If you want to get products for a single category use this:
category = Categorie.objects.filter(category_slug='<slug-to-search>').first()
product = Products.objects.filter(category=category)
But if you want the product for multiple categories use this:
categories = Categorie.objects.all()
products = Products.objects.filter(category__in=categories)
Related
i am creating a new django eccomorce website now in product detail page here is my code
the problem is i cant see product name correct in html page problem with first()
when i use first then only product name showing but all products have same name i have 8 producs in my page eight product name same to first just like overwriting also i cant use for loop with first()
i will add some pics
urls.py
path('collection/<str:cate_slug>/<str:prod_slug>',views.product_view,name="productview"),
views.py
def product_view(request,cate_slug,prod_slug):
if (Category.objects.filter(slug=cate_slug, status=0)):
if (Products.objects.filter(slug=prod_slug, status=0)):
products = Products.objects.filter(slug=prod_slug, status=0).first()
context = {'products':products}
else:
messages.error(request,"no such product found")
return redirect("collection")
else:
messages.error(request,"no such category found")
return redirect("collection")
return render(request,"product_view.html",context)
models.py
class Products(models.Model):
category = models.ForeignKey(Category,on_delete=models.CASCADE)
slug = models.CharField(max_length=150, null=False, blank=False)
product_name = models.CharField(max_length=150, null=False, blank=False)
product_image = models.ImageField( upload_to=get_image,null=True,blank=True)
description = models.TextField(max_length=500,null=False,blank=False)
original_price = models.IntegerField(null=False,blank=False)
selling_price = models.IntegerField(null=False,blank=False)
status = models.BooleanField(default=False,help_text="0=default , 1=Hidden")
trending = models.BooleanField(default=False,help_text="0=default , 1=Trending")
meta_title = models.CharField(max_length=150,null=False,blank=False)
meta_keyword = models.CharField(max_length=150,null=False,blank=False)
meta_description = models.CharField(max_length=400,null=False,blank=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.product_name
productview.html
{% block content %}
<h1>{{ products.product_name }} </h1>
{% endblock %}
i just want correct product name for every category i stucked here in morning helping are appreciated thank you all for helping till now
I think you need to loop through your produckts:
{% for product in products %}
<h1>{{ product.product_name }}</h1>
{% endfor %}
view:
def product_view(request,cate_slug,prod_slug):
if (Category.objects.filter(slug=cate_slug, status=0).exists()):
if (Products.objects.filter(slug=prod_slug, status=0).exists()):
products = Products.objects.filter(slug=prod_slug, status=0)
context = {'products':products}
else:
messages.error(request,"no such product found")
return redirect("collection")
else:
messages.error(request,"no such category found")
return redirect("collection")
return render(request,"product_view.html",context)
Note that usually the model name is singular, so it should be class Products(models.Model):
views.py
def download(request, wallpaper_name):
try:
wallpaper = Wallpaper.objects.get(name=wallpaper_name)
similar_wallpapers = wallpaper.tags.similar_objects()[:2]
except Exception as exc:
wallpaper = None
similar_wallpapers = None
messages.error = (request, 'Sorry! data does not exist')
context = {'wallpaper': wallpaper, 'similar_wallpapers': similar_wallpapers}
return render(request, 'Wallpaper/download.html', context)
models.py
class Tags(models.Model):
tag = models.CharField(max_length=100)
def __str__(self):
return self.tag
class Wallpaper(models.Model):
name = models.CharField(max_length=100, null=True)
size = models.CharField(max_length=50, null=True)
pub_date = models.DateField('date published', null=True)
resolution = models.CharField(max_length=100, null=True)
category = models.ManyToManyField(Category)
tags = TaggableManager()
Device_Choices = [
('PC', 'pc'),
('mobile', 'mobile')
]
Devices = models.CharField(max_length=20,choices=Device_Choices, default= 'PC')
image = models.ImageField(upload_to='Wallpaper/Images/', default="")
def __str__(self):
return self.name
download.html
<div class="tag">
<h3>Tags</h3>
<ul>
<li>{{wallpaper.tags}}</li>
</ul>
</div>
I want all the tags of that particular wallpaper to be rendered
and if possible please tell me if there is any other way to handle tags, because using taggit its very difficult i am getting manny errors
Tags are a many-to-many relation so you need to use .all in your template to get them. However, this will just show you the queryset, so you need to loop through them to render their names:
<ul>
{% for tag in wallpaper.tags.all %}
<li>{{ tag.name }}</li>
{% endfor %}
</ul>
I have this model.py file:
class Category(models.Model):
title = models.CharField(max_length=255, verbose_name="Title")
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.title
class Video(models.Model):
title = models.CharField(max_length=128)
description = models.TextField(default='')
thumbnail = models.ImageField(default='default_thumbnail.png', upload_to='thumbnails')
date_posted = models.DateTimeField(default=timezone.now)
category = models.ForeignKey(
Category,
on_delete=models.SET_DEFAULT,
#null=True,
default=1,
verbose_name="Category"
)
def __str__(self):
return self.title
Each video has its own category and I want to display on one page a given number of films in each category.
Currently, I'm only showing the last 5 videos on the page:
def home(request):
latest_videos = Video.objects.all().order_by('-date_posted')[:5]
categories = Category.objects.all()
context = {
'latest_videos': latest_videos,
#'categories': categories,
}
return render(request, 'videos/home.html', context)
I have no idea how to display a given number of movies in each category. I tried to send all the videos and query them on the template, but this is probably impossible.
Any ideas? I'm still learning Django, but this time I found a problem I can't solve all day.
Thanks
I don't know how many categories do you need to show in your template but one way to do this is like:
def home(request):
ready_data = []
all_categories = Category.objects.prefetch_related('video_set').all() # Note that video_set is your default related query name
for _c in all_categories:
related_videos = _c.video_set.all().order_by('-date_posted')[:5]
ready_data.append({"category_id": _c.id, "category_title": _c.title, "related_videos": related_videos})
context = {
'data': ready_data
}
return render(request, 'videos/home.html', context)
And you should also change this part of your template to something like:
{% for d in data %}
<p> category: {{ d.category_id }}, {{ d.category_title }} </p>
{% for v in d.related_videos %}
<h3> Videos </h3>
<p> {{ v.id }}- {{v.title}} </p>
{% endfor %}
{% endfor %}
This way you can show each category and 5 last of it's related videos.
Web that does not filter questions using categories.
Where is the error?
Thanks!
template
{% for categoria in categorias %}
<p>{{ categoria.categoriaEUS }}</p>
{% endfor %}
models.py
class Pregunta(models.Model):
categoria = models.ManyToManyField(Categoria, null=True, blank=True)
textoES = models.TextField(null=True, blank=True)
textoEUS = models.ManyToManyField(Euskara, null=True, blank=True)
class Categoria(models.Model):
categoriaES = models.CharField(max_length=50, null=True, blank=True)
categoriaEUS = models.CharField(max_length=50, null=True, blank=True)
views.py
def pregunta_list(request,categoria_id):
preguntas = Pregunta.objects.filter(categoria='categoria_id').order_by('id')
paginator = Paginator(preguntas,1)
page = request.GET.get('page')
preguntas = paginator.get_page(page)
return render(request, 'pregunta/pregunta.html', {'preguntas': preguntas})
def categoria_list(request):
categorias = Categoria.objects.all()
return render(request, 'pregunta/categoria.html', {'categorias': categorias})
urls.py
path('',
views.pregunta_list,
name='preguntas/<int:pk>/',
),
You can not put the parameter and the name, since the path that is constructed will not contain that parameter. If later the user visits the link, then the parameter does not exists.
You thus should create a path with:
path(
'preguntas/<int:categoria_id>/',
views.pregunta_list,
name='pregunta_list'
),
and in the template, you can then render the url with:
{% for categoria in categorias %}
<p>{{ categoria.categoriaEUS }}</p>
{% endfor %}
You also used a string literal instead of an identifier in the view:
def pregunta_list(request, categoria_id):
preguntas = Pregunta.objects.filter(categoria=categoria_id).order_by('id')
paginator = Paginator(preguntas,1)
page = request.GET.get('page')
preguntas = paginator.get_page(page)
return render(request, 'pregunta/pregunta.html', {'preguntas': preguntas})
I am trying to get the average of the rating (found in the review model) for each product across all the products within a given category. I am having trouble doing this. The relevant urlconf, view, and template are below:
url(r'^category/(?P<category_id>\d+)/$', 'view_product_category'),
class Productbackup(models.Model):
website = models.CharField('Product name', max_length = 200)
website_url = models.URLField('Product URL')
category = models.ForeignKey(Categories)
def __unicode__(self):
return self.website
class ProductbackupForm(ModelForm):
class Meta:
model = Productbackup
def get_avg_rating(self):
reviews = Reviewbackup.objects.filter(product=self)
count = len(reviews)
sum = 0
for rvw in reviews:
sum += rvw.rating
return (sum/count)
class Reviewbackup(models.Model):
review = models.CharField('Review', max_length = 2000)
rating = models.IntegerField(max_length=200)
product = models.ForeignKey(Product)
def __unicode__(self):
return self.review
class Categories(models.Model):
category = models.CharField('Category_second', max_length = 200)
def __unicode__(self):
return unicode(self.category)
def view_product_category(request, category_id):
allproduct = Productbackup.objects.filter(category_id=category_id)
#get average for each product within a category
return render_to_response('reserve/templates/view_category.html', {'allproduct':allproduct},
context_instance=RequestContext(request))
{% for product in allproduct %}
{{ product.website }}: Direct link<br>
#average rating for that product
{{ product.get_avg_rating }}
{% endfor %}
I will add method on Product model to get avg rating.
class Productbackup(models.Model):
website = models.CharField('Product name', max_length = 200)
website_url = models.URLField('Product URL')
category = models.ForeignKey(Categories)
def __unicode__(self):
return self.website
def get_avg_rating(self):
reviews = Reviewbackup.objects.filter(product=self)
count = len(reviews)
sum = 0
for rvw in reviews:
sum += rvw.rating
return (sum/count)
In template :
{% for product in allproducts %}
{{ product.website }}: Direct link<br>
#average rating for that product
{{ product.get_avg_rating }}
{% endfor %}
Note: passing 'allproducts' not 'product' as in your code. So update the view code accordingly. In your code {% for product in product %} is using same variable name, which isn't correct.
Much effective(without iterations) way to do this is using aggregations with Avg() method,
class Productbackup(models.Model):
website = models.CharField('Product name', max_length = 200)
website_url = models.URLField('Product URL')
category = models.ForeignKey(Categories)
def __unicode__(self):
return self.website
def get_avg_rating(self):
reviews = Reviewbackup.objects.filter(product=self).aggregate(rating_avg=Avg('rating'))
return (reviews['rating_avg'])
In template :
{% for product in allproducts %}
{{ product.website }}: Direct link<br>
#average rating for that product
{{ product.get_avg_rating }}
{% endfor %}