Uable to get the product name from the model - python

I've create 3 models for the Order processing. However, I couldn't show the product name on template for every single order. Does my for loop logic or 'get' method go wrong?
models.py:
class Product(models.Model):
product_name = models.CharField(max_length=200)
price = models.DecimalField(decimal_places=2, max_digits=10, blank=True)
created = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=255, unique=True)
def __str__(self):
return self.product_name
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
item = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
ordered = models.BooleanField(default=False)
def __str__(self):
return f"{self.quantity} of {self.item.product_name}"
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
ordered = models.BooleanField(default=False)
def __str__(self):
return self.user.username
view.py:
def user_info(request):
orders = Order.objects.filter(user=request.user, ordered=True).order_by('-start_date')
context = {
'orders': orders,
}
return render(request, 'home.html', context)
home.html:
{% for order_item in orders.items.all %}
<p>{{ order_item.item.product_name }}</p>
{% endfor %}

You are passing orders from your view which is a queryset so you can't do orders.items.all. You should do a for loop to loop over orders and then get the items:
{% for order_item in orders %}
<p>product names for order id {{order_itme.id}}:</p>
{% for item in order_item.items.all %}
<p>{{ item.item.product_name }}</p>
{% endfor %}
{% endfor %}
Note that this will renders all items for all orders. You should filter the result if you just need one or some of them.

Related

problem with displaying ManyToMany Field in Dango templates

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

filtering reviews according to product django

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

if statement and for loop problem in django html

I am trying to print all the orders related to a specific customer. I used a for loop to access my orders in the html file, and i used an if statement to make sure that the order is related to the customer.
{% for order in orders %}
{% if customer.name == order %}
{{ order }}
{% endif %}
{% endfor %}
in my views I gave my html file access to these variables.
def orderss(request, pk):
Customer = customer.objects.get(id=pk)
orders = Order.objects.all()
context = {
'customer':Customer,
'orders': orders,
}
return render(request, 'Inventory_Management/orders.html', context)
to reach this page i used a button
View Orders
the url is the one below
path('orders/<str:pk>/', orderss, name="orderss")
related models
class Order(models.Model):
STATUS = (
('Pending', 'Pending'),
('Out for delivery', 'Out for delivery'),
('Delivered', 'Delivered'),
)
order_head = models.ForeignKey(order_header, blank=False, null=True, on_delete=models.SET_NULL)
items = models.ForeignKey(item, blank=False, null=True, on_delete=models.SET_NULL)
Quantity = models.CharField(max_length=100)
date_created = models.DateTimeField(auto_now_add=True, null=True)
total = models.CharField(max_length=100)
status = models.CharField(max_length=200, null=True, choices=STATUS)
def __str__(self):
return '{self.order_head.Buyer}'.format(self=self)
class customer(models.Model):
name = models.CharField(max_length=12, blank=False)
phone = models.CharField(max_length=12, blank=False)
email = models.CharField(max_length=50, blank=False)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class order_header(models.Model):
date_created = models.DateTimeField(auto_now_add=True, null=True)
User = models.CharField(max_length=100, blank=False, default="Seller")
Type = models.CharField(max_length=100, default="cash")
Buyer = models.ForeignKey(customer, blank=True, null=True, on_delete=models.SET_NULL)
Note = models.CharField(max_length=100, blank=True, default="Discount: ")
Order_Id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
def __str__(self):
return 'Order Customer: {self.Buyer}, Order Id: {self.Order_Id}'.format(self=self)
now the problem is no orders appear when I press the button, all i get is a blank page even though the specific customer has a number of orders. Help appreciated! Please Help!
In template you're trying to compare name field that is string with object (Order). I guess you thought that name will be compared with order string representation using __str__ method.
Try this:
views.py
Customer = customer.objects.get(id=pk)
orders = order_header.objects.filter(Buyer=Customer)
context = {'orders': orders}
template
{% for order_head in orders %}
{% for order in order_head.order_set.all %}
{{ order }}
{% endfor %}
{% endfor %}

Returning Quantity of Current Cart Entry using Django View

I have the following view where I want to return the quantity of the current cart entry.
def test_view(request):
cart_obj, new_obj = Cart.objects.new_or_get(request)
my_carts_current_entries = Entry.objects.filter(cart=cart_obj)
product_quantity = request.POST.get('product_quantity')
return render(request, 'carts/test.html', {'my_cart': cart_obj, 'my_carts_current_entries': my_carts_current_entries})
How would I reference the current entry quantity, e.g. if there is an entry in the database called 23x Chicken Nuggets I want it to return the quantity.
On the template if I return:
{{ my_carts_current_entries }}
it will return all the current entries but without the quantity.
For clarity I have included an extract of my models.py from the said application:
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True)
count = models.PositiveIntegerField(default=0)
total = models.DecimalField(default=0.00, max_digits=10, decimal_places=2)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = CartManager()
def __str__(self):
return "Cart:{} User:{} Items:{} Total:£{}".format(self.id, self.user, self.count, self.total)
class Entry(models.Model):
product = models.ForeignKey(Product, null=True)
cart = models.ForeignKey(Cart, null=True)
quantity = models.PositiveIntegerField(default=0)
def __str__(self):
return self.product.name
try this in template:
{% for cart in my_carts_current_entries %}
{{ cart.product }} - {{ cart.quantity }}
{% endfor %}

Finding the Cross-Section of two List views in one Django template

I have two models that feed one view.
models.py
class Item(models.Model):
item_name = models.CharField(max_length=100)
item_type = models.ForeignKey(Item_type, on_delete=models.SET_NULL, null=True)
owned_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)****
added_at = models.DateTimeField('date item added')
updated_at = models.DateTimeField('last update')
def __str__(self):
return self.item_name
class Item_status(models.Model):
item = models.ForeignKey(Item, on_delete=models.SET_NULL, null=True)
borrower = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
loaned_at = models.DateTimeField(default=None, blank=True, null=True)
due_back = models.DateTimeField(default=None, blank=True, null=True)
def __time__(self):
return self.loaned_at
def itemname(self):
return (self.item.item_name)
I have the following view
views.py
class LoanedItemsByUserListView(LoginRequiredMixin,generic.ListView):
model = Item_status
template_name ='catalog/item_status_list_borrowed_user.html'
paginate_by = 10
def get_queryset(self):
return Item_status.objects.filter(borrower=self.request.user).order_by('due_back')
def get_context_data(self, **kwargs):
context = super(LoanedItemsByUserListView, self).get_context_data(**kwargs)
context['Owned_list'] = Item.objects.filter(owned_by=self.request.user, item_type = 1)
context['Loaned_list'] = Item_status.objects.exclude(borrower=self.request.user).exclude(borrower__isnull=True)
return context
I would like to find the cross section of the 'Owned_list' and the 'Loaned_list' in a single template
Something like
<h2>Loaned Books</h2>
{% if Owned_list %}
<ul>
{% for thing in Owned_list.item_name and in Loned_list.item.item_name %}
<li>
{{thing}}
</li>
{% endfor %}
</ul
{% else %}
<p>There are no books in the library.</p>
{% endif %}
I have take a look at the django documentation here https://docs.djangoproject.com/en/1.11/topics/class-based-views/generic-display/, and around SO but not found exactly what I am looking for.
Thanks!

Categories