Twig: Finding the sum of values of rows in column - sum

How do I find the total value of all the rows in a column with Twig? For example I have a column "QTY" that will list number of quantities of each row, I want the sum of the total ROWS of QTY (not the sum of qty). What is the tag/logic in Twig?
I have something like this:
<table class="tablesorter">
<thead>
<th>DA</th>
<th>Part</th>
<th>Batch</th>
<th>Qty</th>
</thead>
{% for getbatches in getbatch %}
<tr>
<td>{{getbatch.dano}}</td>
<td>{{getbatch.partno}}</td>
<td class="highlight">{{getbatch.batchno}}</td>
<td>{{getbatch.inqty}}</td>
</tr>
{% endfor %}
</table>
For the rows that populate, I would like the count of the column of QTY, or any column.

Base on your code and according to that you want to get Count of rows in Qty column you can try
<table class="tablesorter">
<thead>
<th>DA</th>
<th>Part</th>
<th>Batch</th>
<th>Qty</th>
</thead>
{% set row_count = 0 %}
{% for getbatches in getbatch %}
<tr>
<td>{{getbatch.dano}}</td>
<td>{{getbatch.partno}}</td>
<td class="highlight">{{getbatch.batchno}}</td>
<td>{{getbatch.inqty}}</td>
</tr>
{% set row_count = row_count + 1 %}
{% endfor %}
</table>
if you want to show that amount somewhere (like a span) you can use <span>{{ row_count }}</span> after
UPDATED
A better solution to show the rows count anywhere if your twig template might be just showing the count of getbatches:
<span>Row count: </span><span>{{ getbatches is defined ? getbatches|length : 0 }}</span>

If you print rows of a table in twig and wany to get the "count of rows in QTY column", you should pass this data to twig from doing a simple count() on the array of rows. If you want to do it "the hard way", you could do:
{% set numRows = 0 %}
{% for .... %}
{% set numRows = numRows + 1 %}
{% endfor %}
but as #TheLittlePig said, twig's purpose is to display data, not do calculations

Related

Macro to surface models to other schemas - dbt_utils.star()

Problem
Currently in my CI process, I am surfacing specific models built to multiple schemas. This is generally my current process.
macros/surface_models.sql
{% set model_views = [] %}
{% for node in graph.nodes.values() %}
{% if some type of filtering criteria %}
{%- do model_tables.append( graph.node.alias ) -%}
{% endif %}
{% endfor %}
{% for view in model_views %}
{% set query %}
'create view my_other_schema.' ~ table ~ 'as (select * from initial_schema.' ~ table ~ ');'
{% endset %}
{{ run_query(query) }}
{% endfor %}
while this works, if the underlying table/view's definition changes, the view created from the above macro will return an error like: QUERY EXPECTED X COLUMNS BUT GOT Y
I could fix this by writing each query with each query's explicit names:
select id, updated_at from table
not
select * from table
Question
Is there a way to utilize the above macro concept but using {{ dbt_utils.star() }} instead of *?

CS50 Finance History Problem with SQL SELECT

I don't understand why I can't SELECT the 'transaction' column from my TABLE portfolio. I created a TABLE using the syntax below:
CREATE TABLE 'portfolio' ('transaction' integer primary key autoincrement,
'datetime' datetime, user_id bigint, 'symbol' varchar(5), 'price' numeric(8,
2), 'shares' integer, 'total' numeric(8, 2));
The transaction keeps a running count of buy/sell orders. When I have transaction in the SELECT statement, it gives me an error, see below:
RuntimeError: near "transaction": syntax error [SQL: 'SELECT transaction,
datetime, symbol, shares, price FROM portfolio WHERE user_id = 2']
(Background on this error at: http://sqlalche.me/e/e3q8)
If I don't include transaction in the python code, then everything works and the table is displayed on the webpage. What is preventing me from selecting transaction? In the code, I included transaction.
#app.route("/history")
#login_required
def history():
"""Show history of transactions"""
#create table
history = db.execute("SELECT transaction, datetime, symbol, shares, price FROM portfolio WHERE user_id = :user_id", user_id = session["user_id"])
history_info = []
for info in history:
transaction = info["transaction"]
datetime = info["datetime"]
symbol = info["symbol"]
shares = info["shares"]
price = info["price"]
total = abs(shares * price)
history_info.append({"transaction":transaction, "datetime":datetime, "symbol":symbol, "shares":shares, "price":price, "total":total})
return render_template("history.html", history_info = history_info)
The html below is what will be displayed on the webpage. Currently, I left off the transaction.
{% extends "layout.html" %}
{% block title %}
History
{% endblock %}
{% block main %}
<table class="table table-bordered">
<thead>
<th>Purchase Date/Time</th>
<th>Symbol</th>
<th>Shares</th>
<th>Price</th>
<th>Total</th>
</thead>
<tbody>
{% for stock in history_info %}
<tr>
<td>{{ stock.datetime }}</td>
<td>{{ stock.symbol }}</td>
<td>{{ stock.shares }}</td>
<td>{{ stock.price }}</td>
<td>{{ stock.total }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
Resolved....
transaction is a reserved word.
Try putting it in brackets [transaction] and see if that works for you.

Show item quantity in shopping cart for a product when on the collections page

I'm in need of some help, what I'd like to do is best described as follows:
When on the collections page
If Product X is added 2 times to the cart
Then add the number 2 next to that product
So the customer knows what products are already inside the cart
So basically, if taking a look at the collections page, I want to be able to see what products are already added into the cart.
I've tried this:
<!-- From 'product-grid-item.liquid' of the default Supply theme -->
{% assign count = 0 %}
{% for item in cart.items %}
{% if product.variants.first.id == item.id %}
{% assign count = count | plus: 1 %}
{% endif %}
{% endfor %}
{% if count > 0 %}<span>{{ count }}</span>{% endif %}
But it simply returns a 1 for Product X. It should return a 2 since it's added twice.
What am I doing wrong?
Here's the working code:
{% assign count = 0 %}
{% for item in cart.items %}
{% if product.id == item.product.id %}
{% assign count = count | plus: item.quantity %}
{% endif %}
{% endfor %}
{% if count > 0 %}<span>{{ count }}</span>{% endif %}
This is because cart.items returns the line items. So it will only return once per unique item id. If you want to count the total item quantity for any item id you need to look at line_item.quantity. Reference docs.shopify.com/themes/liquid-documentation/objects/cart

creating and accessing arrays in liquid templates

Was first looking for a means to select certain existing products in order to place title, image, description on another page (or even within another product page - as some products are combined to make other products) within Shopify.
The method below was the only one I seem to come across for creating an array within Shopify. (the split method).
The next part of the equation, is to use the values from {{ myArray }}, to select the matching var, and to then spit out the different values stored within that array.
However, my attempt does not work. Is there a way to add keys to the other arrays (i.e, p1, p2, p3 arrays), in order to make the selecting of them easier during the for loop?
{% assign myArray = "p1|p3" | split: "|" %}
{% assign p1 = "Product One|product-one|This is my description of product one, and it must be a single paragraphy without any html formatting. The length is not an issue.|product_one_image.jpg" | split:"|" %}
{% assign p2 = "Product Two|product-two|This is my description of product two, and it must be a single paragraphy without any html formatting.|product_two_image.jpg" | split:"|" %}
{% assign p3 = "Product Three|product-three|This is my description of product three, and it must be a single paragraphy without any html formatting.|product_three_image.jpg" | split:"|" %}
{% for item in myArray %}
<h4>{{ item[0] }}</h4>
<p>{{ item[2] }}</p>
{% endfor %}
Continuity flow is wrong in your code.
Here's what you need to do
Load product elements for each product into an array
{% capture list %}
{% for product in products %}
{{ product.title }}|{{ product.handle }}|{{ product.description}}|{{ product.featured_image }}{% if forloop.last %}^{% endif %}
{% endfor %}
{% endcapture %}
{% assign p_list = list | split: "^" %}
Now p_list contains all the products as each element in the array. It is time to get the output.
{% for p_item in p_list %}
{% assign item = p_item | split: "|" %}
<h4>{{ item[0] }}</h4>
<p>{{ item[2] }}<p>
{% endfor %}
Once you start the for loop it will iterate through each value in your array, so indexing (using []) won't work since the array is already being iterated.
In the example above, you began iterating through the list and then attempted to index item, which will not work. If you wanted to index the array then do not make a for loop, in the list above the array only has 2 items but you selected an index outside of the available indexes, this is because the array position starts at 0. so that <p> tag should've been item[1] and outside of the for loop.
To do a for loop. do this:
{% for item in array %}
<h4>{{ item }}</h4>
{{ continue }}
<p>{{ item }}</p>
{% endfor %}
The continue tag will cause it to iterate to the next item on the for loop.

Django: Grouping by Dates and Servers

So I am trying to emulate google app's status page: http://www.google.com/appsstatus#hl=en but for backups for our own servers. Instead of service names on the left it'll be server names but the dates and hopefully the pagination will be there too. My models look incredibly similar to this:
from django.db import models
STATUS_CHOICES = (
('UN', 'Unknown'),
('NI', 'No Issue'),
('IS', 'Issue'),
('NR', 'Not Running'),
)
class Server(models.Model):
name = models.CharField(max_length=32)
def __unicode__(self):
return self.name
class Backup(models.Model):
server = models.ForeignKey(Server)
created = models.DateField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=2, choices=STATUS_CHOICES, default='UN')
issue = models.TextField(blank=True)
def __unicode__(self):
return u'%s: %s' % (self.server, self.get_status_display())
My issue is that I am having a hell of a time displaying the information I need. Everyday a little after midnight a cron job will run and add a row for each server for that day, defaulting on status unknown (UN).
My backups.html:
{% extends "base.html" %}
{% block content %}
<table>
<tr>
<th>Name</th>
{% for server in servers %}
<th>{{ created }}</th>
</tr>
<tr>
<td>{{ server.name }}</td>
{% for backup in server.backup_set.all %}
<td>{{ backup.get_status_display }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock content %}
This actually works but I do not know how to get the dates to show. Obviously {{ created }} doesn't do anything but the servers don't have create dates. Backups do and because it's a cron job there should only be X number of rows with any particular date (depending on how many servers we are following for that day).
Summary
I want to create a table, X being server names, Y being dates starting at today while all the cells being the status of a backup. The above model and template should hopefully give you an idea what my thought process but I am willing to alter anything. Basically I am create a fancy excel spreadsheet.
I suggest adding a function to get the dates you want to show, that's independent of a Server instance. Then you can use it both to get the recent backups and to get the dates for the header. In models.py:
from django.db import models
import datetime
def recent_dates():
return [datetime.date.today() - datetime.timedelta(days=days)
for days in range(-6, 1)]
class Server(models.Model):
...
def backup_for_date(self, date):
next_date = date + datetime.timedelta(days=1)
return self.backup_set.get(created__gte=date, created__lt=next_date)
def recent_backups(self):
return [self.backup_for_date(date) for date in recent_dates()]
Then, if you use the function in views.py:
from django.shortcuts import render_to_response
from myapp.models import Server, recent_dates
def status(request):
servers = Server.objects.all()
return render_to_response('status.html',
{'dates': recent_dates(), 'servers': servers}
)
...you can use the recent_dates variable to print the headers in the template:
{% extends "base.html" %}
{% block content %}
<table>
<tr>
<th>Name</th>
{% for date in recent_dates %}
<th>{{ date }}</th>
{% endfor %}
</tr>
{% for server in servers %}
<tr>
<td>{{ server.name }}</td>
{% for backup in server.recent_backups() %}
<td>{{ backup.get_status_display }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock content %}
Using this method also makes sure the cells don't get shifted out of position if data is missing. The code I provided will raise an exception in the call to the get() method inside backup_for_date() if data is missing, but backup_for_date() could easily be modified to return None in that case.