I have an app that shows the history of products ordered in a restaurant, and to get the data of the restaurant, i have the following view:
def restaurant_orders(request):
restaurant = get_restaurant(request.user.restaurant.user_id)
products = list(restaurant.restaurante.values_list("id"))
items = Item.objects.filter(product_id__in=products).order_by('order_id')
context = {'items': items}
return render(request, 'pages/orders_restaurant.html', context)
In template i'm displaying as follows:
<div class="col-lg-7">
<h2>Histórico de Pedidos</h2>
{% for value in items %}
<ul class="list-group list-group-flush"></ul>
<li class="list-group-item bg-light">
<h4>Order {{ value.order_id }}</h4>
{{ value.quantity }} X {{ value.product }}
<span class="float-right">R$ {{ value.price }}</span>
<li class="font-weight-bold list-group-item bg-light">Client Name
<span class="float-right">{{ value.order.name }}</span>
</li>
</li>
<br>
{% endfor %}
</div>
but doing it this way I get each data separate, and I would like to know if there is any way to group the data that has a field with the same value. The result I getting now is this, and I would like something like this.
model.py
class Item(models.Model):
order = models.ForeignKey(Order, related_name="items", on_delete=models.CASCADE)
product = models.ForeignKey(Product, related_name="order_items", on_delete=models.CASCADE)
price = models.DecimalField(max_digits=5, decimal_places=2)
quantity = models.PositiveIntegerField(
validators= [
MinValueValidator(1),
MaxValueValidator(20),
]
)
You need loop over a Order model query.
You can filter it throught the related name property in the Item model.
orders = Order.objects.filter(items__product_id__in=products)
Then, in your template, you can loop through the orders and the items in each one's:
<ul> {# apply your markup... #}
{% for order in orders %}
<li>
{{ order }}
<ul>
{% for item in order.items.all %}
<li>{{ item.product }} {# ... #}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Related
On my main page i want to show a category just like {{ post.body }} but instead {{ post.body }} would be {{ post.category }} here.
{% extends "base.html" %}
{% block title %}Articles{% endblock title %}
{% block content %}
{% for post in post_list %}
<div class="card">
<div class="card-header">
<span class="font-weight-bold">{{ post.title }} |
</span> ·
<span class="text-muted">by {{ post.author }} |
{{ post.created_at }}</span>
</div>
<div class="card-body">
<!-- Changes start here! -->
<p>{{ post.body }}</p>
<p>{{ post.category }}</p>
Edit |
Delete |
Category
</div>
<div class="card-footer">
{% for comment in post.comment_set.all %}
<p>
<span class="font-weight-bold">
{{ comment.author }} ·
</span>
{{ comment }}
</p>
{% endfor %}
</div>
<!-- Changes end here! -->
</div>
<br />
{% endfor %}
{% endblock content %}
but cannot to figure out how. But cannot figure out how.
Here is my models
from django.conf import settings
from django.db import models
from django.urls import reverse
class Category(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return (self.name)
def get_absolute_url(self):
return reverse("home")
class Post(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
category = models.ManyToManyField(Category, related_name='categories')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("post_detail", kwargs={"pk": self.pk})
class Comment(models.Model):
article = models.ForeignKey(Post, null=True, blank=True, on_delete=models.CASCADE)
comment = models.CharField(max_length=140)
author = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,)
def __str__(self):
return self.comment
def get_absolute_url(self):
return reverse("post_list")
Thanks in advance
Added {{ post.category }} in here
{% extends "base.html" %}
{% block title %}Articles{% endblock title %}
{% block content %}
{% for post in post_list %}
<div class="card">
<div class="card-header">
<span class="font-weight-bold">{{ post.title }} |
</span> ·
<span class="text-muted">by {{ post.author }} |
{{ post.created_at }}</span>
</div>
<div class="card-body">
<!-- Changes start here! -->
<p>{{ post.body }}</p>
<p>{{ post.category }}</p>
Edit |
Delete |
Category
</div>
<div class="card-footer">
{% for comment in post.comment_set.all %}
<p>
<span class="font-weight-bold">
{{ comment.author }} ·
</span>
{{ comment }}
</p>
{% endfor %}
</div>
<!-- Changes end here! -->
</div>
<br />
{% endfor %}
{% endblock content %}
expected to see a category instead got post.category.None
To show the category in the HTML just like a property, you can add a property method in the model class and use it HTML, like this:
class Post(models.Model):
...
#property
def categories(self):
return ', '.join([x.name for x in self.category.all()]
Then use it template like:
{{ post.categories }}
Alternatively as it is a ManyToMany field, you can iterate through it in the template and render the categories:
{{ for c in post.category }} {{ c.name }} {% if not forloop.last %}, {% endif %} {{ endfor }}
Explanation of property method: property method allows you to convert a function to an attribute of the object of that class. self in the property method refers to itself (or the object itself). using self.category.all(), you are accessing the manytomany relation between Post and Category class. I am running a loop and access each of the Category objects connected to the Post object (the main object which are using in the template/html) and I am joining the names of the Category objects' names to form a comma separated string.
There is my html template which works perfectly. No template errors.
{% extends 'learning_logs/base.html' %}
{% block title %}Topic {% endblock title %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>There are no entries for this topic yet.</li>
{% endfor %}
</ul>
{% endblock content %}
You will find below my view.py. In actual fact the application does not any error.
def topic(request, topic_id):
"""Show a single topic and all its entries."""
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
topic = models.ForeignKey('Topic', on_delete = models.CASCADE, max_length = 200)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add = True)`
I am always getting all the food items in all Categories.
I want to display each Category with each food item.
Need to display Category with item belonging to that Category.
Please someone help me on this issue to resolve. I have tried looking over internet but couldn't find the solution to it
models.py
class Category(models.Model):
category_name = models.CharField(max_length=50)
def __str__(self):
return self.category_name
class Menu(models.Model):
dish_name = models.CharField(max_length=200, verbose_name='Name of Dish')
Desc = models.TextField(verbose_name='Dish Description')
Amount = models.IntegerField(null=False, blank=False, verbose_name='Amount of Dish')
date_posted = models.DateTimeField(default=timezone.now, verbose_name='Dish Date Posted')
category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1)
def __str__(self):
return self.dish_name
views.py
def menu(request):
products = Menu.objects.all()
categories = Category.objects.all()
data = {}
data['products'] = products
data['categories'] = categories
template = 'food/menu.html'
return render(request, template, data)
html
{% for category in categories %}
{% if categories %}
<div class="col-xs-12 col-sm-6">
<div class="menu-section">
<h2 class="menu-section-title">{{ category.category_name }}</h2>
<hr>
{% endif %}
{% for i in products %}
<div class="menu-item">
<div class="menu-item-name">{{ i.dish_name}}</div>
<div class="menu-item-price">Rs {{ i.Amount}}</div>
<div class="menu-item-description">{{ i.Desc}}</div>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
you are not filtering products based on categoris.
I would suggest doing something like this with data:
data = {
'categories': {
category: Menu.objects.filter(category=category) for category in categories
}
}
and in html you can:
{% for category, products in categories.items %}
{% if products %}
<div class="col-xs-12 col-sm-6">
<div class="menu-section">
<h2 class="menu-section-title">{{ category.category_name }}</h2>
<hr>
{% for i in products %}
<div class="menu-item">
<div class="menu-item-name">{{ i.dish_name}}</div>
<div class="menu-item-price">Rs {{ i.Amount}}</div>
<div class="menu-item-description">{{ i.Desc}}</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
I want to express the detailview as the picture. I want to code the box part in the template of the picture.
enter image description here
It is as follows now.
views.py
#login_required
def product_detail(request, id, product_slug=None):
product = get_object_or_404(Product, id=id, slug=product_slug)
return render(request, 'shop/detail.html', {'product': product})
I think it should be modified to class. I would like to explain it by representing DetailView and ListView together in detail_template. I modified only views.py as shown below.
class ProductDetailView(DetailView, ListView):
model = Product
template_name = 'shop/detail.html'
context_object_name = 'latest_question_list'
#login_required
def get_queryset(self, id, product_slug=None):
product = get_object_or_404(Product, id=id, slug=product_slug)
return render(self, 'shop/detail.html', {'product': product})
This error occurs. AttributeError: 'ProductDetailView' object has no attribute 'user'
urls.py
urlpatterns = [
.........
path('<int:id>/<product_slug>/', product_detail, name='product_detail'),
.........
]
detail.html
{% extends 'base.html' %}
{% block title %}Product Detail{% endblock %}
{% block content %}
<div class="col">
<div class="alert alert-info" role="alert">Detail</div>
<div class="container">
<div class="row">
<div class="col-4">
<img src="{{product.image.url}}" width="100%">
</div>
<div class="col">
<h1 class="display-6">{{product.cname}}</h1>
<p class="card-text">{{product.pname}}</p>
<h5><span class="badge badge-secondary">Description</span>{{product.description|linebreaks }}</h5>
{% if product.author.username == user.username %}
Update
Delete
{% endif %}
{% if product.author.username != user.username %}
Inquiry
{% endif %}
Continue shopping
</div>
</div>
</div>
<p></p>
<div class="col">
<div class="alert alert-info" role="alert">Products added by registrants</div>
<div class="container">
{% for product in products %}
<div class="row">
{% if product.user.username == user.username %}
<div class="col-4">
<img src="{{product.image.url}}" width="auto" height="250">
</div>
<div class="col">
<h1 class="display-6">{{product.pname}}</h1>
<h5><span class="badge badge-secondary">Description</span>{{product.description|linebreaks}}</h5>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% endblock %}
Please help me how to fix it. I would also appreciate it if you would recommend any textbooks that I can refer to.
I have a similar situation. I wanted to display create form, detail and list on the same page:
urls:
example_urlpatterns = [
path('', views.ExampleCreateView.as_view(), name='_list'),
path('new/', views.ExampleCreateView.as_view(), name='_create'),
path('<int:pk>/', views.ExampleCreateView.as_view(), name='_detail'),
path('<int:pk>/del', views.ExampleDeleteView.as_view(), name='_del'),
]
urlpatterns = [
# ...
path('example/', include(example_urlpatterns)),
# ...
]
As you can see, I have two views, ExampleCreateView (also providing detail and list) and ExampleDeleteView for deleting. ExampleCreateView is primarily a create view:
class ExampleCreateView(CreateView):
template_name = 'example.html'
form_class = ExampleCreateForm
model = Example
def form_valid(self, form):
pass # Stuff to do with a valid form
# add user info from request to the form
def get_form_kwargs(self, *args, **kwargs):
kwargs = super().get_form_kwargs(*args, **kwargs)
kwargs['user'] = self.request.user
return kwargs
# Create appropriate context
def get_context_data(self, **kwargs):
kwargs['object_list'] = Example.objects.order_by('ip') # list
try: # If we have pk, create object with that pk
pk = self.kwargs['pk']
instances = Example.objects.filter(pk=pk)
if instances:
kwargs['object'] = instances[0]
except Exception as e:
pass # No pk, so no detail
return super().get_context_data(**kwargs)
Because I'm inheriting from CreateView, all the form processing is taken care of by default.
Adding the line kwargs['object_list'] =... makes it work as a list view, and the try block after that line makes it work as a detail view.
In the template all relevant parts are displayed:
{% if object %}
{% comment %}
...display the object... (Detail section)
{% endcomment %}
{% endif %}
{% if form %}
{% comment %}
...display the form... (Create section)
{% endcomment %}
{% endif %}
{% if object_list %}
{% comment %}
...display the list... (List section)
{% endcomment %}
{% endif %}
Let me know if this helps
Currently I have applied like this
views.py : modified
#method_decorator(login_required, name="dispatch")
class ProductDetailView(DetailView):
model = Product
template_name = 'shop/detail.html'
def get_context_data(self, **kwargs):
context = super(ProductDetailView, self).get_context_data(**kwargs)
context['product_list'] = Product.objects.all()
return context
index = ProductDetailView.as_view()
detail.html : modified
<div class="col">
<div class="alert alert-info" role="alert">Products added by this registrant</div>
<div class="container">
{% for prdt in product_list %}
{% if product.author.username == prdt.author.username %}
{% if product.pname != prdt.pname %}
{{ prdt }}<br>
{% endif %}
{% endif %}
{% endfor %}
</div>
enter image description here
{% set pages = craft.entries.section('interests').all() %}
{% nav page in pages %}
<div class="nav__column">
<li class="nav__parent">
{{ page.getLink() }}
{% ifchildren %}
<ul>
{% children %}
</ul>
{% endifchildren %}
</li>
</div>
{% endnav %}
When using this every nav item has the class of nav parent
Can I determine what classes are on the nav item depending on whether it is a child or parent nav item?
Just wrap that class in the ifchildren conditional, e.g:
{% set entries = craft.entries.section('pages') %}
<ul id="nav">
{% nav entry in entries %}
<li{% ifchildren %} class="nav__parent{% endifchildren %}">
{{ entry.title }}
{% ifchildren %}
<ul>
{% children %}
</ul>
{% endifchildren %}
</li>
{% endnav %}
</ul>
As an aside, your example code is invalid markup; <li> elements can only appear within a valid list type, e.g. <ul> or <ol>.