I have 3 tables related for listing a product with features, i want to list FeatureItem values with for loop in template html file. I ve tried to write a view class but i couldn't succeed. Any Suggestion which approach for views.py and template.html file would be best solution? Thanks.
class Item(models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
slug = models.SlugField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
feature = models.ForeignKey(Feature, on_delete=models.CASCADE)
class FeatureItem(models.Model):
feature_title = models.CharField(max_length=100)
feature_description = models.CharField(max_length=100)
feature_id = models.ForeignKey(Feature, on_delete=models.CASCADE)
class Feature(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
urls.py:
urlpatterns = [
...
path('some_url', views.some_view_function, name='some_url'),
...
]
views.py:
def some_view_function(request):
feature_items = models.FeatureItem.objects.all()
context = {
'feature_items' : feature_items,
...
}
return render(request, 'some_template.html', context=context)
some_template.html:
...
<div>
{% for feature_item in feature_items %}
Title: {{ feature_item.feature_title }}
{% endfor %}
...
Related
I am working on a Django project where I would like to display list of all categories on the homepage as links. When one clicks a category, they are taken to a page whereby all the posts under that field are displayed. Inside the list of posts page, I would like to show the title as the name of the category. Also I would like the url to have the name of the category.
My code is working fine in rendering those pages, but my issue is that it uses id instead of the slug field.
When I replace .id with .slug, I get the error:
ValueError at /category/electricals
Field 'id' expected a number but got 'electricals`
Here is my Models.py:
class Category(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(null=True, blank=False)
slug = models.SlugField(unique=True, null=True)
def __str__(self):
return self.title
class Service(models.Model):
category = models.ForeignKey('Category', on_delete=models.CASCADE)
title = models.CharField(max_length=100)
image = models.ImageField(null=True, blank=False)
description = models.TextField(null=False, blank=False)
service_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True, editable=False)
slug = models.SlugField(unique=True, null=True)
def __str__(self):
return self.title
And here is my views.py;
def landing_page(request):
categorys = Category.objects.all()
context = {'categorys':categorys}
return render(request, 'users/homepage.html', context)
def categories(request, cats):
category_services = Service.objects.filter(category=cats)
context = {'cats':cats,'category_services':category_services }
return render(request, 'users/categories.html', context)
My urls.py:
path('category/<str:cats>', views.categories, name='category'),
Template:
{% for category in categorys %}
<!-- <li><a href="{% url 'category' category.slug %}" >{{category.title}}</a></li> -->
<li><a href="{% url 'category' category.id %}" >{{category.title}}</a></li>
{% endfor %}
I have tried replacing using the code below but it does not work
category_services = Service.objects.filter(category=cats.replace('id', 'slug'))
I have an app for a shopping list, and I want to display values from my ingredients ManyToManyField but what I am getting instead is the name of the recipe that I created.
Could you please advise me on how to correctly do it?
models.py
class Ingredients(models.Model):
name=models.CharField(max_length=100, default='-', blank=True, unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'składnik'
verbose_name_plural = 'składniki'
def __str__(self):
return str(self.name)
class Category(models.Model):
name=models.CharField(max_length=250, default='-', blank=True, unique=True)
slug = models.SlugField(unique=True, blank=True)
class Meta:
ordering = ('name',)
verbose_name = 'kategoria'
verbose_name_plural = 'kategorie'
def get_absolute_url(self):
return reverse("kategoria", kwargs={"slug": self.slug})
def __str__(self):
return str(self.name)
class Recipe(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, default='-')
name = models.CharField(max_length=400, blank=False, unique=False)
body = models.TextField(blank=True, default='')
ingredients = models.ManyToManyField(Ingredients)
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True)
date_created = models.DateTimeField('Utworzono', default=timezone.now)
last_updated = models.DateTimeField('Ostatnia zmiana',auto_now=True)
when_to_eat = models.DateField('Kalendarz', default=timezone.now)
tags = TaggableManager()
slug = models.SlugField(unique=True, blank=True)
class Meta:
ordering = ('name',)
verbose_name = 'przepis'
verbose_name_plural = 'przepisy'
def get_absolute_url(self):
return reverse("przepis", kwargs={"slug": self.slug})
def __str__(self):
return str(self.name)
views.py
class RecipeListView(ListView):
model = Recipe
template_name ='recipe_list.html'
queryset = Recipe.objects.all()
urls.py
urlpatterns = [
path('przepisy/', views.RecipeListView.as_view(), name='recipe_list'),
path('przepis/<slug:slug>/', views.RecipeDetailView.as_view(), name='przepis'),
]
recipe_list.html
<p class="card-text">Składniki:<br>
{% for ingredient in object_list %}
<li>{{ingredient.name}}</li>
{% endfor %}
</p>
you should try something like this:
{% for ingredients in object_list %}
{% for ingredient in ingredients.name.all %}
<li>{{ingredient.name}}</li>
{% endfor %}
{% endfor %}
Try this:
<p class="card-text">Składniki:<br>
{% for recipe in object_list %}
{% for ingredient in recipe.ingredients.all %}
<li>{{ingredient.name}}</li>
{% endfor %}
{% endfor %}
</p>
As you want to get all name from your Ingredients model but you are using {{ingredient.name}} which will show you all name from your Recipe Model. You need to be write {{ingredient.ingredients.name}} So the code will be looke like this
<p class="card-text">Składniki:<br>
{% for ingredient in object_list %}
<li>{{ingredient.ingredients.name}}</li>
{% endfor %}
</p>
As you are using Recipe model in your ListView so when you are writing {{ingredient.name}} it's similar to like this Recipe Model > name when we are writing {{ingredient.ingredients.name}} it's similar to Recipe Model > ManyToManyField of ingredients > garbing name from Ingredients model
I want my reviews that are on that particular product to be shown only on that product not on any other . I do not know how to filter it. Recently it is showing all the reviews on every product.
My models.py file is:
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product , on_delete=models.CASCADE, null=True)
date = models.DateTimeField(auto_now_add=True)
text = models.TextField(max_length=3000 , blank=True)
rate = models.PositiveSmallIntegerField(choices=RATE_CHOICES)
likes= models.PositiveIntegerField(default=0)
dislikes = models.PositiveIntegerField(default=0)
def __str__(self):
return self.user.full_name
my product models.py is:
class Product(models.Model):
title = models.CharField(max_length=110)
slug = models.SlugField(blank=True, unique=True)
status = models.CharField(choices=CATEGORY_CHOICES, max_length=10)
price = models.DecimalField(decimal_places=2, max_digits=6)
quantity=models.IntegerField(default=1)
discount_price=models.FloatField(blank=True, null=True)
size = models.CharField(choices=SIZE_CHOICES, max_length=20)
color = models.CharField(max_length=20, blank=True, null=True)
image = models.ImageField(upload_to=upload_image_path)
description = RichTextField(max_length=1000)
featured = models.BooleanField(default=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
time_stamp = models.DateTimeField(auto_now_add=True)
my product detail views.py is:
class ProductDetailSlugView(ObjectViewedMixin,DetailView):
queryset = Product.objects.all()
context_object_name = "object_list"
template_name = "product_detail.html"
def get_context_data(self, *args ,**kwargs):
context = super(ProductDetailSlugView , self).get_context_data(*args, **kwargs)
context['reviews'] = Review.objects.all()
# context['reviews'] = Review.objects.filter(product=self.request.product)
cart_obj, new_obj = Cart.objects.new_or_get(self.request)
context['cart'] = cart_obj
# context['comments'] = Comment.objects.all()
return context
my product_detail.html is:
<!-- {% for review in reviews %}-->when i do this with my code it show me all the product
<!-- <h1>{{review.text}}{{review.rate}}</h1>-->
<!-- {% endfor %}-->
{% for review in product.review_set.all %}
{{ review.text }}
{% endfor %}
You do not need to make a query separately for your reviews. You can simply loop over them using your instance of Product in the template. Also for some reason you have set context_object_name = "object_list" try this:
{% for review in object.review_set.all %}
{{ review.text }}
{% endfor %}
Here review_set is simply the default related_name set by Django which is the related models name in lowercase with _set appended to it. You can chose to set the related name yourself like so if you want:
product = models.ForeignKey(Product, related_name='reviews', on_delete=models.CASCADE, null=True)
Anyway if you insist on modifying the view you can simply do this:
class ProductDetailSlugView(ObjectViewedMixin,DetailView):
queryset = Product.objects.all()
context_object_name = "object_list"
template_name = "product_detail.html"
def get_context_data(self, *args ,**kwargs):
context = super(ProductDetailSlugView , self).get_context_data(*args, **kwargs)
context['reviews'] = Review.objects.filter(product=self.object)
cart_obj, new_obj = Cart.objects.new_or_get(self.request)
context['cart'] = cart_obj
# context['comments'] = Comment.objects.all()
return context
And then you can use this:
{% for review in reviews %}
{{ review.text }}
{% endfor %}
I want to fetch all the foreignkey table's attribute and show it in my HTML template. Here is my code in models, views and in the template:
models.py:
class OrderDashboard(models.Model):
title = models.CharField(max_length=100,default=None)
single_slug = models.SlugField(max_length=100, default=1)
description = models.TextField(max_length=1000)
thumb = models.ImageField()
date = models.DateField()
def __str__(self):
return self.title
class OrderScenario(models.Model):
webshop = models.CharField(max_length=100)
title = models.ForeignKey(OrderDashboard, default=None, on_delete=models.SET_DEFAULT)
order_qty = models.TextField(max_length=10)
order_date = models.DateField()
current_status = models.CharField(max_length=100)
ticket = models.CharField(max_length=200)
remark = models.TextField()
class Meta:
verbose_name_plural = "Scenario"
def __str__(self):
return self.webshop
Views.py:
def single_slug(request, single_slug):
report = OrderDashboard.objects.get(single_slug=single_slug)
return render(request, 'order_dashboard/report.html', {'report': report,
'OrderScenario': OrderScenario.objects.all})
I only want to view all the scenarios added in OrderScenario with respect to Title in OrderDashboard.
You should use backward relationship here; if you are passing the slug through the url, you can use:
views.py:
def single_slug(request, slug): # why you have self as the first argument?
report = OrderDashboard.objects.get(single_slug=slug)
return render(request, 'order_dashboard/report.html', {'report': report}
report.html:
{{ report.title }}
</p>Order Scenarios:</p>
{% for scenario in report.orderscenario_set.all %}
{{ scenario }}
{% endfor %}
I have two applications (blog and category). On the post list template I would like to get the category blog name and description.
I have tried to put the import category model in the blog view, but nothing show up. So I have made two views rendering the same template, but it does not work.
Blog models:
from django.db import models
from django.utils import timezone
from autoslug import AutoSlugField
from category.models import Category
class Post(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE,
default = '')
title = models.CharField(max_length=200)
...
class Meta:
verbose_name = "Post"
verbose_name_plural = "Posts"
ordering = ['created_date']
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
category models:
class Category(models.Model):
name = models.CharField(max_length=200)
slug = AutoSlugField(populate_from='name', default='')
parent = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.CASCADE)
description = models.TextField(max_length=200)
class Meta:
unique_together = ('slug', 'parent',) # Enforcing that there can not be two
verbose_name_plural = "categories" # categories under a parent with same
# slug
def __str__(self): # __str__ method elaborated later in
full_path = [self.name] # post. use __unicode__ in place of
# __str__ if you are using python 2
k = self.parent
while k is not None:
full_path.append(k.name)
k = k.parent
return ' -> '.join(full_path[::-1])
Blog view:
def post_list(request):
posts = Post.objects.all()
cat_blog = Category.objects.get(pk=1)
context = {
'posts': posts,
'cat_blog': cat_blog
}
return render(request, 'blog/post_list.html', context)
Category view:
def cat_blog(request):
cat_blog = Category.objects.get(pk=1)
return render(request, 'blog/post_list.html', {'cat_blog': cat_blog})
post_list.html:
<div class="section-header text-center">
{% for category in cat_blog %}
<h1>{{ category.name }}</h1>
<p class="tag">{{ category.description }}</p>
{% endfor %}
</div>
<div class="row py-5">
{% for post in posts %}
// This part is fine
{% endfor%}
The post loop is fine. How can't I get the category name and description in my section header?
One URL gives one View gives one template.
You use the View to give context to the template to render.
def post_list(request):
posts = Post.objects.all()
cat_blog = Category.objects.get(pk=1)
context = {
'posts': posts,
'cat_blog': cat_blog
}
return render(request, 'blog/post_list.html', context)
Your url.py file should point to the post_list view.