What is the right way of iterating over django form? - django

I am dynamically creating a form like so;
def partial_order_item_form(item):
"""dynamic form limiting optional_items to their items"""
class PartialOrderItemform(forms.Form):
quantity = forms.IntegerField(widget=forms.TextInput(attrs={'size':'2', 'class':'quantity','maxlength':'5'}))
option = forms.ModelChoiceField(queryset=OptionalItems.objects.filter(item=item),widget= forms.RadioSelect())
return PartialOrderItemform
with that,i can render the options in the template like so and it works perfectly;
{% for item in form.option %}
{{ item }}
{%endfor%}
but this {{ item.price }} does not work. I need a brief explanation on why its not working and a way to go about it.
I have looked around but failed to find similar questions (i must not be searching the right way ), links are much appreciated.

I think you need the field queryset if you want to iterate. Use manage.py shell to instantiate a form and introspect. Why not use form.as_XXX?

Related

How to make a for loop break on counter in Django Templates?

How can I make the for product in products loop break after the if condition is fulfilled 3 times. I have been trying to set up a counter but that isn't working... because set is not accepted inside of for loops. Though testing it out a bit more it isn't being accepted anywhere.
When I use set it throws this exception or a variation of it: Invalid block tag on line 11: 'set', expected 'endblock'. Did you forget to register or load this tag?
I am aware that I should put all the logic I'm using Templates for inside of the view and then pass it through the dictionary but it would take too much time to research everything about that and i just want to be done with this.
Honestly I am really tired it is 6am and idk what to do. Thank you for your help in advance. :)
Edit: I know I have to use namespace() for set to be able to propagate across scopes. But set itself is still raising the same exception as above.
Edit2: I thought that django uses jinja2 as it's templating language but it seems like that is not the case. I fixed the mentions of jinja2 as I haven't changed any of the defaults that come with a fresh install of django.
HTML
{% for category in categories %}
<div>
<h5 class="text-line"><span>{{category.name}}</span></h5>
</div>
<!-- Cards Container -->
<div class="shop-cards">
{% set counter = 0 %}
{% for product in products %}
{% if product.category.categoryID == category.categoryID %}
<!-- CARD 1 -->
<div class="card">
<image class="product-image" src="{% static 'images/product-4.png' %}"></image>
<div class="card-category-price">
<h3 class="product-name">{{product.name}}</h3>
<h3 class="product-price">{{product.price}}</h3>
</div>
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
You can't (by design).Django is opinionated by design, and the template language is intended for display and not for logic.
You can use Jinja instead.
Or, you can do the complicated stuff in Python and feed the results to the template language through the context. Bear in mind that appending arbitrary objects to a list in Python is a cheap operation. So (in a CBV) something like
context['first_three'] = self.get_first_three( whatever)
...
def get_first_three(self, whatever):
first_three = []
for obj in ...:
if complicated stuff ...
first_three.append( obj)
if len(first_three) == 3:
break
return first_three
BTW you can't (easily?) implement break in Django templating, but you can easily give it the ability to count:
class Counter( object):
def __init__(self):
self.n = 0
def value(self):
return self.n
def incr(self):
self.n += 1
return ''
In the context pass context['counter'] = Counter()
In the template refer to {{counter.value}} as much as you want, and in a conditional where you want to count occurences, use {{counter.incr}}. But, it's hacky, and probably best avoided.
The problem seems to arise due to a misconception of the templating functionality. It is to be used mainly for display purposes and not filtering purposes, and you are facing a filtering problem:
I want to filter the 3 first elements of a list that fulfill a specific condition
is your main issue and templating frameworks will be poor at solving your issue, whereas this is exactly what python and Django's ORM are good at.
Why don't you first filter in Django, then display in template? For example as follows:
...
products = queryset.filter(abc=condition)[:3]
context = Context({ 'products': products })
return HttpResponse(template.render(context))

django how to store an object in session to use in multiple templates

Im working with django and i would like to store a object (in session?) so i can use this in multiple templates. So similar to the "user" that is always accessible, id like to add one of my own. So i dont have to add it every time in render(request,
What i try so far:
def login_character(request, character_name):
request.session['character'] = Character.objects.get(name=character_name)
return HttpResponseRedirect(reverse('index'))
Template:
{% if 'character' in request.session %}
<p>Jeej there is some character</p>
{{ request.session.character.name }}
{% else %}
<p>Nope, nothing here</p>
{% endif %}
But that doesn't seem to work,
Can someone help me out or point in the right direction?
With kind regards,
Hans
I think you meant
{% if 'character' in request.session %}
instead of
{% if 'character' in request.session['character'] %}
Also, you wrote that you need sessions, because you want an object to be always accessible, without a need to explicitly add it in every view. In this case I think a template context processor would probably be a better choice.
Update: You also need to make sure that django.core.context_processors.request is among template context processors in your settings file. See also this answer.

Using the Django assignment_tag built-in tag the right way

I'm working on a project in Django.
Earlier today, I discovered the new (Django >= 1.4) assignment_tag. I immediately decided that it was just what I needed EVERYWHERE and threw some logic into one that executed a very simple query against the database and returned the resulting queryset. The function I wrapped takes an argument that allows the invoking context to specify how many results to grab, directly in the template when I am using the template tag.
It is quite convenient - I don't have to update my view when I decide this list should have 5 items, not 3 - but it seems like one of those gray areas where we aren't supposed to tread (i.e. pushing application logic into templates) when writing good, maintainable Django code.
Now, a couple of hours separated from writing the code, I'm wondering if I should scrap the assignment_tag entirely.
Code:
models.py:
class SomeObject(models.Model):
is_active = models.BooleanField(default=False)
(...)
templatetags/myapp_tags.py:
from django import template
from myapp.models import SomeObject
register = template.Library()
#register.assignment_tag
def get_someobjects_list(max_results=0):
queryset = SomeObject.objects.filter(is_active=True)
if max_results == 0:
return queryset
elif max_results > 0:
return queryset[:min(max_results, queryset.count())]
else:
return None
templates/myapp/chunks/someobject_list.html:
{% load myapp_tags %}
{% get_someobjects_list as someobjects_list %}
# or {% get_some_objects_list 5 as someobjects_list %} ... flexible!
{% if someobjects_list %}
<ul>
{% for someobject in someobjects_list %}
<li>
<a href="{{ someobject.get_absolute_url }}">
{{ someobject.name }}
</a>
</li>
{% endfor %}
</ul>
{% else %}
<span>No someobjects exist</span>
{% endif %}
I was really excited to discover these existed - it's convenient for me in this particular case. Now that my excitement over finding a new feature has passed, it seems pretty clear that I'm misusing it. The example given in the Django docs seems like a better application of this - grabbing the string representation of current datetime, something that doesn't require a DB query. My worry is that I'm setting myself up for heartache if I start using this pattern regularly. Following the slippery slope all the way down: I'll end up not even bothering to pass a context to my templates and ALL my DB queries will be hidden away in template tags where nobody would think to look for them.
It seems the code would be cleaner if I just threw out this whole "great idea" I had when I discovered assignment_tags and created a custom model manager instead.
Are there other clean ways of accomplishing this that I am missing? Are manager methods the consensus best way among Django developers?
assignment template tags are especially helpful if you need to get some information into the template context for a few pages of a website, but don't want to (or can't) put the info into every view on the website, and don't want to or can't rely on a context processor.
they basically guarantee that your information will be available in the template.

Django HTML snippet for a model

I am new to Django and I am trying to find out how can I associate a HTML snippet with a model.
My HTML snippet is just a div. I want to reuse that div (you can think of it like a thumbnail)
Situation is like this: In my main page I want to show x objects and in my search page I want to show more objects. But the representation is the same.
I can write in the mainpage.html and searchpage.html the desired way of transforming the model object into a div but I am not sure what is the best way to reuse that transform?
I can add a function to my model which returns a HTML div, then I can call it from mainpage and searchpage templates. But that will couple the model and representation, which I believe is not a very nice thing to do.
If I am not mistaken inclusion_tags are the way to go but in which file should I keep the function definition?
As you rightly say, you don't want html in your models, it's goes against the MVC pattern.
Models are for storing data. Views are for selecting the data to present whilst Templates are used for the actual presentation of data. (See this note on django's interpretation of MVC).
To answer your question, you need a template (or even a template tag), to represent your model, say model_block.html. Something like
{% if obj %}
<div id=obj.id>
{{ obj.name }}
</div>
{% endif %}
Then include your template in your mainpage.html like
{% for obj in object_list %}
{% include 'model_block.html' %}
{% endfor %}
You can do the same thing in your searchpage.html, passing a different object_list variable from your view.

How do I create a filtered Dropdown Choice field in Django using ajax?

I am trying to create a dynamic filtered drop down choice fields,i gone through below blog but it confusing,can any one suggest easy way to do this in django.
I'm trying to create a dynamically filtered dropdown Choice field in Django. I've tried the steps outlined here, but I don't understand it.
How do I create a filtered Dropdown Choice field in Django using ajax?
You can use dajaxproject (django+ajax). Example: http://www.dajaxproject.com/forms/ It's so easy.
Maybe you mean something like this?
http://code.google.com/p/django-ajax-selects/
I have this implemented in a couple of projects, and it's working well. If you are looking for a kind of search form for foreign keys, have a look at an app I started some weeks ago:
https://github.com/schneck/django-foreignkeysearch
I only had a small array of drop down choices I needed to display, so I chose to be lazy and not to go the Ajax route but rather used the initial example provided in the blog (his prototype). This will slow down rendering the page if you have many drop-down choices, which I do not have.
The way it worked for me was that I replaced the array:
modelstxt[1] = "1\tEscort\n2\tTaurus";
modelstxt[2] = "1\tAltima\n2\tMaxima";
With template tags that will create the same array while building the page (note I use locations and areas, not models and makes):
areastxt[0] = "0\t--";
{% for location in locations %}
areastxt[{{location.id}}] = "0\t--
{% for area in areas %}
{% if area.location_id == location.id %}
\n{{area.id}}\t{{area.name}}
{% endif %}
{% endfor %}";
{% endfor %}
Disclaimer: I am noob'ish, so I may be committing a noob faux-pas using this approach.