Im working with views and templates.
I've this list in my view
[u'kevinelamo', 50, u'kevin', 4200, u'andres', 200, u'user342', 0, u'cateto', 0]
and I send it to the template..
In the template is parsed like this automatically:
[{"username": "kevinelamo", "time": 50}, {"username": "kevin", "time": 4200}...]
I want to iterate like this:
{% for username,time in llistat_usuaris %}
<h1>My name is <h1>{{username}}
{{time}}
{% endfor %}
But this gave me one char of the list
My name is
[
My name is
{
My name is
"
My name is
u
My name is
s
My name is
e
My name is
r
My name is
n
My name is
a
My name is
m
My name is
e
My name is
How can I handle it? Thanks
If you have this list:
l = [u'kevinelamo', 50, u'kevin', 4200, u'andres', 200, u'user342', 0, u'cateto', 0]
You could convert it to a dictionary:
l_dict = dict(zip(l[::2], l[1::2]))
Which will make l_dict:
{u'andres': 200, u'cateto': 0, u'user342': 0, u'kevin': 4200, u'kevinelamo': 50}
Then iterate over key value pairs in your template:
{% for username, time in l_dict.items %}
<h1>My name is <h1>{{ username }}
{{ time }}
{% endfor %}
Related
Here is my Template :
{% for pr in productlist %}
<ul>
<li><input type="checkbox" name="mylistch" value="{{ pr.productid }}"></li>
<li><input type="hidden" name="mylist" value="{{ pr.productname }}"></li>
<li><input type="number" name="mylist" id="prqty"/></li>
</ul>
{% endfor %}
and View :
pch = request.POST.getlist('mylistch')
pnch = iter(pch)
pr = request.POST.getlist('mylist')
pri = iter(pr)
for pid, pname, ptotal in zip(pnch , pri , pri):
models.Sellinvoiceitems.objects.create(
productid=pid
productname=pname,
totalnumber=ptotal,
sellinvoice = invoice,
stockid = stock
)
Here i checked 5 checkbox with this ids : 6 , 9 , 10 , 12 , 19, But ids : 1 , 2 , 3 ,4 ,5 inserted to db, what is problem here?
My problem seems to be quite standard and I found many solutions, but none which works for a Django view.
I have timestamped items ("conversions") and I want to show the number of items per month. My view deliver this:
2020-05 3
2020-03 2
What I need is this:
2020-05 3
2020-04 0
2020-03 2
models.py:
class Conversion(models.Model):
timestamp = models.DateTimeField()
views.py (thanks to this help):
from django.db.models import Count
from django.db.models.functions import TruncMonth
def conversions_monthly(request):
conv = Conversion.objects.values(month=TruncMonth(
'timestamp')).annotate(count=Count('pk')).order_by('-month')
context = {'conversion': conv}
return render(request, 'dummy/conversions_monthly.html', context)
Template conversions_monthly.html:
{% extends "dummy/base.html" %}
{% block content %}
<table>
{% for c in conversion %}
<tr>
<td>{{ c.month |date:"Y-m" }}</td>
<td class="text-right">{{ c.count }}</td>
</tr>
{% endfor %}
</table>
{% endblock content %}
Data:
[
{
"model": "dummy.conversion",
"pk": 1,
"fields": {
"project": 1,
"timestamp": "2020-03-10T05:00:00Z"
}
},
{
"model": "dummy.conversion",
"pk": 2,
"fields": {
"project": 1,
"timestamp": "2020-03-12T17:00:00Z"
}
},
{
"model": "dummy.conversion",
"pk": 3,
"fields": {
"project": 1,
"timestamp": "2020-05-19T12:00:00Z"
}
},
{
"model": "dummy.conversion",
"pk": 4,
"fields": {
"project": 2,
"timestamp": "2020-05-20T16:10:03Z"
}
},
{
"model": "dummy.conversion",
"pk": 5,
"fields": {
"project": 1,
"timestamp": "2020-05-20T16:30:00Z"
}
}
]
I guess, I have to "aggregate" somehow the min and max date and need something like:
import datetime
from dateutil.relativedelta import relativedelta
result = []
max = date(2020, 5, 20)
min = date(2020, 3, 1)
current = min
while current <= max:
result.append(current)
current += relativedelta(months=1)
which delivers [datetime.date(2020, 3, 1), datetime.date(2020, 4, 1), datetime.date(2020, 5, 1)]
I have no idea how to get these pieces together – or is there a completely different approach for that in Django?
You are on the right path already, here is your code stitched together
# views.py
def index(request):
result = []
# `min` and `max` are keywords in python, so it is bad practice to use them as variable names
_max = datetime.date(2020, 5, 20)
_min = datetime.date(2020, 3, 1)
current = _min
while current <= _max:
result.append({"date": current, "count": 0})
current += relativedelta(months=1)
conversions = Conversion.objects.values(month=TruncMonth(
'timestamp')).annotate(count=Count('pk')).order_by('-month')
# the conditions for checking `i` being smaller than `length` protect you in case there are no conversions in your range
i = 0
length = len(result)
for conversion in conversions:
while i < length and \
not (
result[i]["date"].year == conversion["month"].year and
result[i]["date"].month == conversion["month"].month
):
i += 1
if i < length:
result[i]["count"] = conversion["count"]
context = {'conversion': result}
return render(request, 'dummy/conversions_monthly.html', context)
template
{% extends "dummy/base.html" %}
{% block content %}
<table>
{% for c in conversion %}
<tr>
<td>{{ c.date |date:"Y-m" }}</td>
<td class="text-right">{{ c.count }}</td>
</tr>
{% endfor %}
</table>
{% endblock content %}
Inspired by Nader Alexan I found the following solution which delivers the desired result. _min and _max are no longer fix, but calculated now.
from django.db.models import Count
from django.db.models.functions import TruncMonth
from django.db.models import Max, Min
def conversions_monthly(request):
conversions = Conversion.objects.values(month=TruncMonth('timestamp')).annotate(
count=Count('pk'))
result = []
_min = Conversion.objects.aggregate(Min('timestamp'))[
'timestamp__min'].date().replace(day=1)
_max = Conversion.objects.aggregate(Max('timestamp'))[
'timestamp__max'].date().replace(day=1)
current = _max.replace(day=1)
while current >= _min:
c = conversions.filter(month__year=current.year).filter(
month__month=current.month)
if c:
result.append({"date": current, "count": c[0]['count']})
else:
result.append({"date": current, "count": 0})
current -= relativedelta(months=1)
context = {'conversion': result}
return render(request, 'dummy/conversions_monthly.html', context)
I want to send just one part of an object to template.
I Have 2 models like below:
class Person(models.Model):
name = models.CharField(max_legth=50)
sure_name = models.CharFiled(max_length=50)
class Office(models.Model):
location = models.CharField(max_legth=50)
and I also created a model like below:
class PersonOffice(models.Model):
person = models.ForeignKey(Person)
office = models.ForeignKey(Office)
now, when I take data from database, by PersonOffice.objects.all(),the data is like below:
{
{
"pk": 0,
"person": {
"pk":0,
"name":"Harry",
"sure_name":"Potter"
},
"office":{
"pk":5,
"location":"Toronto"
}
},
{
"pk": 1,
"person": {
"pk":6,
"name":"John",
"sure_name":"Kelly"
},
"office":{
"pk":6,
"location":"NewYork"
}
}
}
I want to send just offices to the template by render function. How can I do it?
thanks
Updated
I want to use it in template with {% for %} loop. for example:
{% for office in Offices %}
<p>Office location: {{ office.location }}</p>
{% endfor %}
I used below code:
offices = PersonOffice.objects.all().values('office')
print(offices)
and below is the result in terminal:
<QuerySet [{'office': 1}, {'office': 2}, {'office': 11}]>
You can use values
PersonOffice.objects.values('office')
This will output a queryset with office for each object.
EDIT:
PersonOffice.objects.values('office__location')
I've created a session list that contains my products, i need to update the quantity of any product by increasing it amount, for that am using an HTML type="number" , i also created a function which take the changed amount and multiplying it value with the current quantity, so lets say the amount of the first product by default is 2 by increasing the number lets say 2 the product amount will become 4 and so on, also the price will be multiplied .
Here are the codes:
<th style="text-align: center;" class="amount-izd">{{value["amount"]}}</th>
<th style="text-align: center; width: 14%;">
<div class="block">
<input type="number" id="myNumber" value="1" min=1 data-amount='{{value["amount"]}}' data-pros='{{value["id"]}}' data-price='
{% if g.currency == "euro" %}
{{format_price(value["price"] * config.SITE_CURRENCIES["euro"]).rsplit(".",1)[0]}}
{% elif g.currency == "dollar" %}
{{format_price(value["price"] * config.SITE_CURRENCIES["dollar"]).rsplit(".",1)[0]}}
{% else %}
{{format_price(value["price"] * config.SITE_CURRENCIES["ruble"]).rsplit(".",1)[0]}}
{% endif %}
'>
<label for="myNumber">qty</label>
</div>
</th>
JQuery codes:
$("input[type='number']").bind('keyup change click', function (e) {
if (! $(this).data("previousValue") ||
$(this).data("previousValue") != $(this).val()
)
{
var currentAmount = $(this).attr('data-amount');
var currentPrice = $(this).attr('data-price');
$(this).closest('tr').find('.amount-izd').text(parseInt(currentAmount) * $(this).val());
$(this).closest('tr').find('.price-izd').text(parseInt(currentPrice) * $(this).val());
$.ajax({
type: 'post',
url: '/standard-{{g.currency}}/profile/'+$(this).attr("data-pros")+'/update/price/' + parseInt(currentPrice) * $(this).val(),
cache: false
}).done(function(data){
if(data.error){
toastr.error(data.error)
}
});
$(this).data("previousValue", $(this).val());
} else {
}
});
And finally views.py :
#profile_route.route("/standard-<set_curr>/profile/cart/", methods=['GET','POST'])
#authorize
def cart_products():
if "cart" not in session:
return render_template("my-cart.html", display_cart = {}, total = 0)
else:
items = session["cart"]
dict_of_products = {}
total_price = 0
for item in items:
product = Goods.query.get(item)
total_price += product.price
if product.id in dict_of_products:
pass
else:
dict_of_products[product.id] = {"qty":1, "name":product.product_name, 'category':product.Category.name, "sizes": product.sizes, "hex_color":product.hex_color, "text_color":product.text_color, "material":product.material, "article":product.article, "price":product.price, "sort": product.sort, "amount": product.amount, 'slug':product.slug, 'public_id' : product.public_id, "id":product.id}
return render_template("my-cart.html", display_cart=dict_of_products, total = total_price)
#profile_route.route("/standard-<set_curr>/profile/<int:id>/update/price/<price>", methods=['GET','POST'])
#login_required
def update_price(id, price):
items = session["cart"]
dict_of_products = {}
for item in items:
product = Goods.query.get(item)
if product.id in dict_of_products:
dict_of_products[id]['price'] = price
return jsonify(success=dict_of_products[id]['price'])
return jsonify(error='No product found.')
If i changed the amount , in console i got a 500 error that says:
return jsonify(success=dict_of_products[id]['price'])
KeyError: 47
Please how to overcome this problem ?
Update:
I was wondering , is it possible to update any value of the dictionary by accessing it directly from JQuery ??
I am using the following code in my Django view
data = {'d':['a','b','c']}
return render_to_response('login/invalid.html',data)
Now i want my invalid.html page to have the code to convert the list ['a','b','c'] to a javascript variable array so that i can populate a dropdown menu. But i cannot convert these elements into a javascript array.
var arr = "{{ 'd' }}"
takes the list as a string and not as an array
Please help
This code creates a drop down using an array
<select >
<script type="text/javascript">
{% autoescape off %}
var veg = {{ d }}
{% endautoescape %}
for (i = 0; i < veg.length; i++) {
document.write('<option>')
document.write(veg[i])
document.write('</option>')
}
</script>
</select>
d = json.dumps(['a','b','c'])
#d = serializers.serialize("json", ['a','b','c'])
#data={"d":json.dumps(['1','2','3','4'])}
#data={}
data = {'d':d}
#data["read"] = json.dumps(",".join(['abc']))
#return render_to_response('login/invalid.html',json.dumps(data),context_instance=RequestContext(request))
return render_to_response('login/invalid.html',data,context_instance=RequestContext(request))
You probably want to serialize your data as json:
import json
d = json.dumps(['a','b','c'])
# now d actually has a json string
data = {'d':d}
return render_to_response('login/invalid.html',data)
Then in your template
// arr now holds the list
{% autoescape off %}
var arr = {{ d }}
{% endautoescape %}
console.log(arr);
arr.doSomething();
Convert the list into JSON via json and output it in the template, marking it safe as required.