Django: Check if value in list - django

I have a QuerySet with several entries order.order_items.all. I want to check in my template if any of these items in my list contain the foreign_key discount. After one is found, I want to display that a discount_code was used for the order. How would you solve this?
Example:
<QuerySet [OrderItem: #k9ukvrfvjk - 1x Test Ticket 1, OrderItem: #k9ukvrfvjk - 1x Test Ticket 2]>

Rather than doing it in Template, I think its better to do it in the view. For example:
context['discount'] = order.order_items.filter(discount_id=<discount_id>).exists()
return render(request, 'template', context=context)
and in template:
{% if discount %}
// discounted related codes
{% endif %}
Update
Maybe you can get it simply by:
{% item in order.order_items.all %}
{% if item.discount %}
{{ item.discount.discount_code }}
{% endif %}
{% endfor %}

Related

Django - for each field value

I have a question.
In my view, I return a dataset which includes:
Category
Product
Price
I want to say something like the below, where I show UI elements related to a category as a whole.
is it possible?
{% for item.category in products %}
Not directly. You would do
{% for item in products %}
...
{{ item.category}}
Or if item.category is itself an iterable you can nest loops. If it's the set of related objects you need a .all (c.f. python obj.foo_set.all() )
{% for item in products %}
...
{% for category in item.category.all %}
{% for item in products %}
{{item.Category}}
{{item.Product}}
{{item.Price}}
{% endfor %}

django ModelChoiceField: how to iter through the instances in the template?

I am trying to get access to the instances of a ModelChoiceField to render them the way I want in a template by displaying several fields of the instances.
class MyForm(forms.Form):
mychoices = forms.ModelChoiceField(
queryset=ObjectA.objects.all(), widget=forms.RadioSelect(), empty_label=None
)
This does not work:
{% for choice in form.mychoices %}
{{ choice.pk}}
{% endfor %}
I also tried to use the queryset but it does not render anything
{% for choice in form.mychoices.queryset %}
{{ choice.pk}}
{% endfor %}
Any idea?
Thanks
{% for choice in form.mychoices.field.queryset %}
{{ choice.pk }}
{% endfor %}
Notice the extra .field. It's a bit strange the first time you come across it, but it gives you what you want. You can also access the choices attribute of that object, instead of accessing queryset directly, but you'll need to access the first element of the choice to get the PK of the instance, like this:
{% for choice in form.mychoices.field.choices %}
{{ choice.0 }}
{% endfor %}

what is the right way to query a manytomany field in django

so i have a model which is,
class Category(SmartModel):
item=models.ManyToManyField(Item)
title=models.CharField(max_length=64,help_text="Title of category e.g BreakFast")
description=models.CharField(max_length=64,help_text="Describe the category e.g the items included in the category")
#show_description=check box if description should be displayed
#active=check box if category is still avialable
display_order=models.IntegerField(default=0)
def __unicode__(self):
return "%s %s %s %s " % (self.item,self.title, self.description, self.display_order)
and as you may see, it has a manytomany field
item=models.ManyToManyField(Item)
i want to return all the items in a template, here is my views.py for this
def menu(request):
categorys= Category.objects.all()
items= categorys.all().prefetch_related('item')
context={
'items':items,
'categorys':categorys
}
return render_to_response('menu.html',context,context_instance=RequestContext(request))
here is how am doing it in the templates,
<ul>
{% for item in items %}
<li>{{ item.item }}
</li>
</ul>
{% endfor %}
after all this,this is what it is returning in my web page,
<django.db.models.fields.related.ManyRelatedManager object at 0xa298b0c>
what am i doing wrong,I have really looked around but all in vain, hoping you can help me out and thanking you in advance
Exactly, you have a many to many manager. You need to actually query something... like all()
{% for item in items %}
{% for i in item.item.all %}
{{ i }}
{% endfor %}
{% endfor %}
Based on your variable naming, I think you're confusing the results of prefetch_related as a bunch of items. It is in fact returning a QuerySet of Category objects.
So it would be more intuitive to call them categories.
{% for category in categories %}
{% for item in category.item.all %}
{{ item }} {# ...etc #}
Try to use:
categorys= Category.objects.prefetch_related('item').all()
And then in template:
{% for category in categorys %}
{% for item in category.item.all %}
{{ item }}
{% endfor %}
{% endfor %}

reduce django db calls

I noticed that my django code calls my database very often with the exact same queries.
I understand that a db hit is made when I actually need the data to display on a page or to evaluate. However, my template code looks like this:
template:
{% if item.listing %}
{{ item.name }} text <strong>{{ item.listing|lowestprice }}</strong> more text
{% else %}
{{ item.name }} even more text
{% endif %}
....
{% for listed_item in item.listing %}
....
{% endfor %}
custom filter:
def lowestprice(value):
try:
val = unicode(value[0].price) + unicode(value[0].symbol)
return val
except:
return "not available"
This code hits my db three times. First on template {% if .. %} second on my custom filter, third on the {% for %} loop.
listing is a method of my models class which is returning a raw SQL queryset with some very expensive joins.
def listing(self):
return Universe.objects.raw("ONE HELL OF A QUERY")
How can I reduce my code to hit the db only once?
Edit: Using with works, but is it possible to avoid db hits on custom filters?
You should use with to do the expensive query once and store it the context.
{% with item.listing as item_listing %}
{% if item_listing %} ... {% endif %} ... etc ...
{% endwith %}

List products by category in Django template

What's the best way to generate HTML which has a heading for each Category, and Products under that category in a Django template?
I toyed with the idea of having a passing a dictionary, or an ordered list...
Take a look at the regroup template filter
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#regroup
With it you could do something like this:
{% regroup products by category as products_by_category %}
{% for c in products_by_category %}
<h1>{{c.grouper}}</h1>
<ul>
{% for p in c.list %}
<li>{{p.name}}</li>
{% endfor %}
</ul>
{% endfor %}
In addition to what #Wade suggests you can also add a method to your Category model to return the products it has.
Example..
class Category:
...
...
def get_products(self):
return Product.objects.filter(category=self)
Then in a template you can..
{% for category in categories %} # assuming categories is passed from the view.
{% for product in category.get_products %}
...
used a sorted list in the view code,
sorted(dom_obj.objects.all(), key=lambda d: d.sort_key)
and then used the filter tag
{% ifchanged %}<h1>{{ prod.cat }}</h1>{% endifchanged %}