I would like to compute the total of a shopping cart in my template:
This is my template with a table of products.
I tried to use a Generator expression in my cart method but it doesn't work.
Any thoughts?
cart.html
<table>
{% if not cart_list %}
{{ "The cart is empty" }}
{% else %}
<tr>
<th>Name</th>
<th>Price</th>
</tr>
{% for product in cart_list %}
<tr>
<td>{{ product.name }}</td>
<td>${{ product.price }}</td>
</tr>
{% endfor %}
<tr>
<td>{{ Total }}</td>
<td>{{ total_prices }}</td>
</tr>
{% endif %}
</table>
views.py
def cart(request):
if request.method == 'GET':
cart_list = Product.objects.filter(in_cart = True)
total_prices = sum(product.price for product in cart_list)
template_cart = loader.get_template('cart/cart.html')
context = {'cart_list': cart_list}
return HttpResponse(template_cart.render(context, request))
Add your total_prices to context variable, if you want it to be visible in the template.
def cart(request):
if request.method == 'GET':
...
total_prices = sum(product.price for product in cart_list)
context = {
'cart_list': cart_list,
'total_prices': total_prices
}
return HttpResponse(template_cart.render(context, request))
But you can try to use aggregate, something like this.
from django.db.models import Sum
Product.objects.filter(in_cart=True).aggregate(Sum('price'))
# you will have something like this -> 34.35 is example
# {'price__sum': 34.35}
Related
I am creating an app for a school schedule using Django. Admin users can currently add classes to a list. Student users can view that list but I want to create a button/link that will add that class object to a separate list that will act as their applied classes.
Models.py
class Class(models.Model):
def __str__(self):
return self.name
name = models.CharField(max_length=50)
crn = models.CharField(max_length=5, validators=[RegexValidator(r'^\d{1,10}$')])
grade_mode = models.CharField(max_length=50)
subject = models.CharField(max_length=3)
course_num = models.CharField(max_length=4, validators=[RegexValidator(r'^\d{1,10}$')])
section_num = models.CharField(max_length=3, validators=[RegexValidator(r'^\d{1,10}$')])
credit_hours = models.FloatField(validators=[MinValueValidator(0.0), MaxValueValidator(5.000)])
teacher = models.CharField(max_length=50)
Views.py
#login_required
#dec.student_required
def index(request):
class_list = Class.objects.all().order_by("-name")
# Allow for Posting of New Classes to Schedule.
if request.method == "POST":
form = ClassesForm(request.POST)
if form.is_valid():
form.save()
form = ClassesForm()
messages.success(request, "Class Added to Registry!")
else:
form = ClassesForm()
context_dict = {'classes': class_list,
'form': form}
return render(request, 'index.html', context=context_dict)
Index.HTML Add Button
<table>
<tbody>
{% if classes %}
{% for class in classes %}
<tr>
<td>Class Name: </td>
<td>Subject: </td>
<td>CRN: </td>
<td>Course Number: </td>
<td>Section Number: </td>
<td>Credit Hours: </td>
<td>Teacher: </td>
<td>Grade Mode: </td>
<td>Add Class</td>
</tr>
<tr>
<td>{{ class.name }}</td>
<td>{{ class.subject }}</td>
<td>{{ class.crn }}</td>
<td>{{ class.course_num }}</td>
<td>{{ class.section_num }}</td>
<td>{{ class.credit_hours }}</td>
<td>{{ class.teacher }}</td>
<td>{{ class.grade_mode }}</td>
<td>
<form method="GET">
{% csrf_token %}
<button class="addToSchedule" type="submit" value="add" name="Add Class">
Add Class
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
{% else %}
<strong>There are no classes added.</strong>
{% endif %}
</table>
Image on Website.
So far I can print out the models on their own separate list as shown above but I don't know where to go in regards to the button or if a button is even the correct way of doing it. I want to click on a button and that model will be added and saved to the Added Classes section above.
I`ve got a table displaying all products. I would like to display the product attribute for each product name. Is it possible to do this in one table like shown below?
Thank you
models.py
class Product(models.Model):
name = models.CharField(max_length=60, unique=True)
attribute = models.ManyToManyField(ProductAttribute)
class ProductAttribute(models.Model):
property = models.CharField(max_length=20) # eg. "resolution"
value = models.CharField(max_length=20) # eg. "1080p"
file.html
{% for product in products %}
<tr>
<td style="font-weight:bold">{{ product.name }}</td>
<td>{{ product.productattribute }}</td>
</tr>
{% endfor %}
views.py
#login_required(login_url="/login/")
def productlist_details(request, shop_id, productlist_id):
shop = Shop.objects.get(pk=shop_id)
products = Product.objects.all()
productattributes = ProductAttribute.objects.all()
context = {
'shop': shop,
'products': products,
'productattributes': productattributes,
}
return render(request, 'productlist_details.html', context)
Using the ifchanged tag (https://docs.djangoproject.com/en/3.1/ref/templates/builtins/#ifchanged) you could do something like:
{% for product in products %}
<tr>
<td style="font-weight:bold">{{ product.name }}</td>
</tr>
{% for attribute in product.attributes.all %}
<tr>
<td>{{ attribute.property }}</td>
</tr>
{% endfor %}
{% endfor %}
try this
{% for product in products %}
<tr>
<td style="font-weight:bold">{{ product.name }}</td>
<td>{{ product.attributes.property }}</td>
</tr>
{% endfor %}
I'm beginner in django and i'm using a read-only db, I just wanna make some selects and show it as a table in my template, but I cant return coulmn by column into my html table, help me,
I'm using a directky raw query
Model.py
from django.db import connection
# Create your models here.
def dictfetchall(cursor):
"Returns all rows from a cursor as a dict"
desc = cursor.description
return [
dict(zip([col[0] for col in desc], row))
for row in cursor.fetchall()
]
def my_custom_sql(self):
with connection.cursor()as cursor:
cursor.execute("""
SELECT EQUIP_ID, LINE_CODE, PLANT_CODE
FROM tbs_rm_mnt_shift_sumr
where SUMR_YMD = '20180405' AND SIDE_CODE = 'T' AND
rownum < 20
""" )
row = dictfetchall(cursor)
return row
view.py
from django.shortcuts import render, redirect, get_object_or_404
from .models import my_custom_sql
# Create your views here.
def show_list(request):
query= my_custom_sql(self='my_custom_sql')
return render(request,'monitoring.html', {'query': query})
monitoring.html
<table border="2" style="solid black">
<tr>
<td>Equip</td>
<td>Line</td>
<td>Plant</td>
{% for instance in query %}
{% for field, value in instance.items %}
<tr>
<td>{{ value }} </td>
</tr>
{% endfor %}
{% endfor %}
</tr>
</table>
browser output:
enter image description here
At the moment you are only outputting one td for each row.
{% for instance in query %}
{% for field, value in instance.items %}
<tr>
<td>{{ value }} </td>
</tr>
{% endfor %}
{% endfor %}
It sounds like should loop inside the tr tag:
{% for instance in query %}
<tr>
{% for field, value in instance.items %}
<td>{{ value }} </td>
{% endfor %}
</tr>
{% endfor %}
However, you can't assume the order of the keys in the dictionary, so you should either access the items by key, or rethink whether you want to use dictfetchall.
{% for instance in query %}
<tr>
<td>{{ instance.EQUIP_ID }} </td>
<td>{{ instance.LINE_ID }} </td>
<td>{{ instance.PLANT_CODE }} </td>
{% endfor %}
</tr>
{% endfor %}
I have a ModelFormSet:
TransactionFormSet = modelformset_factory(Transaction, exclude=("",))
With this model:
class Transaction(models.Model):
account = models.ForeignKey(Account)
date = models.DateField()
payee = models.CharField(max_length = 100)
categories = models.ManyToManyField(Category)
comment = models.CharField(max_length = 1000)
outflow = models.DecimalField(max_digits=10, decimal_places=3)
inflow = models.DecimalField(max_digits=10, decimal_places=3)
cleared = models.BooleanField()
And this is the template:
{% for transaction in transactions %}
<ul>
{% for field in transaction %}
{% ifnotequal field.label 'Id' %}
{% ifnotequal field.value None %}
{% ifequal field.label 'Categories' %}
// what do i do here?
{% endifequal %}
<li>{{ field.label}}: {{ field.value }}</li>
{% endifnotequal %}
{% endifnotequal %}
{% endfor %}
</ul>
{% endfor %}
The view:
def transactions_on_account_view(request, account_id):
if request.method == "GET":
transactions = TransactionFormSet(queryset=Transaction.objects.for_account(account_id))
context = {"transactions":transactions}
return render(request, "transactions/transactions_for_account.html", context)
I want to list all the Transaction information on a page.
How can I list the "account" property of Transaction and the "categories"?
Currently the template shows only their id, I want to get a nice representation for the user (preferrably from their str() method).
The only way I can see that would work is to iterate over the FormSet, get the Ids of the Account and Category objects, get the objects by their Id and store the information I want in a list and then pull it from there in the template, but that seems rather horrible to me.
Is there a nicer way to do this?
Thanks to the comments, I figured it out that what I was doing was pretty dumb and pointless.
This works:
1) Get all Transaction objects
transactions = Transaction.objects.for_account(account_id)
2) Pass to template
context = {"transactions":transactions,}
return render(request, "transactions/transactions_for_account.html", context)
3) Access attributes, done
{% for transaction in transactions %}
<tr>
<td class="tg-6k2t">{{ transaction.account }}</td>
<td class="tg-6k2t">{{ transaction.categories }}</td>
<td class="tg-6k2t">{{ transaction.date }}</td>
<td class="tg-6k2t">{{ transaction.payee }}</td>
<td class="tg-6k2t">{{ transaction.comment }}</td>
<td class="tg-6k2t">{{ transaction.outflow }}</td>
<td class="tg-6k2t">{{ transaction.inflow }}</td>
<td class="tg-6k2t">{{ transaction.cleared }}</td>
</tr>
{% endfor %}
Please help - does flask/wtforms somehow treat the data property of a field differently after an append_entry call or am I just really doing this wrong?
I have a form that gets its data from a yaml file. On the initial GET request, the form populates showing the icons from the {% if ifc.poe.data %} as expected. If either button is hit to add a module or interface, the POST re-renders the page, but now ifc.poe.data is empty and thus no icons are rendered. If you comment out the if ifc.xxx.data portion and uncomment out the actual fields, the fields are rendered with the proper data every time. Is this something with how I'm building the form class or in how I'm handling the POST? What happened to the ifc.xxx.data?
Any help is appreciated, I'm pretty new at this.
forms.py
from flask_wtf import Form
from wtforms import Form as wtfForm # Bad hack to get around csrf in fieldlist
class DevInterface(wtfForm):
e_regex = '^ae(\d+)$'
ifc = StringField("Interface", validators=[DataRequired()])
poe = BooleanField('PoE', validators=[Optional()], default=False)
uplink = BooleanField('Uplink', validators=[Optional()],default=False)
desc = StringField("Description", validators=[Optional()],default='')
voip = StringField("VOIP", validators=[Optional()], default='')
etheropt = StringField("LAG interface", validators=[Optional(),Regexp(e_regex, message='Must designate an ae interface, eg. ae4')])
class DevHardware(wtfForm):
module = SelectField('Module', choices=[
('ex2200-24p','ex2200-24p'),('ex2200-48p','ex2200-48p'),
('ex4200-10g','ex4200-10g'),('ex4200-24f','ex4200-24f')],
default='ex2200-48p')
fpc = SelectField('FPC', choices=[(str(i),str(i)) for i in range(10)], default=0)
class DevOptions():
id = StringField('Device Serial Number', validators=[DataRequired()])
hostname = StringField('Hostname', validators=[DataRequired()])
make = SelectField('Make', choices=[('juniper','Juniper')], default = 'juniper')
class AddDev(Form, DevOptions):
modules = FieldList(FormField(DevHardware), min_entries=1)
interfaces = FieldList(FormField(DevInterface), min_entries=1)
add_ifc = SubmitField()
add_module = SubmitField()
views.py
#app.route('/editdev/<vspc>/<dev>', methods=['GET','POST'])
def editdev(vspc,dev):
from skynet.forms import AddDev
try:
d = s.loaddev(dev)
except IOError as e:
flash(dev + ' does not exist.', category='danger')
return redirect(url_for('editvspc', vspc=vspc))
# Have to change up how the data is presented for the form
d['id'] = dev
ifcs = d['interfaces']
del d['interfaces']
l = []
for i in ifcs:
j={}
j['ifc'] = i
j.update(ifcs[i])
l.append(j)
d['interfaces'] = sorted(l, key=lambda k: k['ifc'])
form = AddDev(request.form, data=d)
if form.add_ifc.data:
form.interfaces.append_entry()
elif form.add_module.data:
form.modules.append_entry()
elif request.method == 'POST' and form.validate():
# Placeholder for now
print 'Updated device'
for error in form.errors:
for e in form[error].errors:
flash(e, category='danger')
return render_template('adddev.html', form=form)
template
{% extends "layout.html" %}
{% import "bootstrap/utils.html" as util %}
{% block content %}
{{ super() }}
<div class="container-fluid">
<h1 align='center'>Add Device</h1>
<form method="post" action="">
{{ form.hidden_tag() }}
<div class="form-group">
<table class="table">
<tbody>
<tr>
<td>{{ form.id.label }}</td>
<td>{{ form.id(size=20) }}</td>
</tr>
<tr>
<td>{{ form.hostname.label }}</td>
<td>{{ form.hostname(size=20) }}</td>
</tr>
<tr>
<td>{{ form.make.label }}</td>
<td>{{ form.make}}</td>
</tr>
</tbody>
</table>
{{ form.add_module }}
<table class="table">
<tbody>
{% for field in form.modules.entries %}
<tr>
<td>{{ field.module.label }}</td>
<td>{{ field.module }}</td>
<td>{{ field.fpc.label }}</td>
<td>{{ field.fpc }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table">
<thead>
<tr>
<th>Interface</th>
<th>Description</th>
<th>PoE</th>
<th>VoIP</th>
<th>LAG</th>
<th>Uplink</th>
</tr>
</thead>
<tbody>
{% for ifc in form.interfaces %}
<tr>
<td>{{ ifc.ifc(size=10) }}</td>
<td>{{ ifc.desc }}</td>
<td>
{% if ifc.poe.data %}
{{ util.icon('flash', style='color:red') }}
{% endif %}
{% if ifc.voip.data %}
{{ util.icon('phone-alt', style='color:green') }}
{% endif %}
{% if ifc.etheropt.data %}
<a class="label label-success">{{ ifc.etheropt.data }}</a>
{% endif %}
{% if ifc.uplink.data %}
{{ util.icon('open', style='color:blue') }}
{% endif %}
</td>
{# <td>{{ ifc.poe }}</td>
<td>{{ ifc.voip }}</td>
<td>{{ ifc.etheropt }}</td>
<td>{{ ifc.uplink }}</td> #}
</tr>
{% endfor %}
</tbody>
</table>
{{ form.add_ifc }}
</div>
<button type="submit" class="btn btn-default">Add Device</button>
</form>
</div>
{% endblock %}