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