Displaying dictionary value in django template - python

All,
I have the following in my views.py
def getgradeform(request):
id1=request.user.get_pf().id
sc=Sc.objects.filter(id=id1)
logging.debug(sc)
logging.debug("++++")
dict={}
dict.update({'sc': sc})
return render_to_response('content/add.html',dict)
Logging.debug gives an output as [<sc: Robert>]
My question is that how do i display Robert in the template .
I have tried the following in the template:<input type ="text" value={{sc}}/> //This gives me the dictionary itself
<input type ="text" value={{dict.sc}}/> //This also doesnt work.
Thanks......

If you want any value in a dictionary, you have to do it on the way
dict.key
(On python you'll write it as dict['key'])
So, to present the value stored with key 'name'
{{ sc.name }}
Anyway, I think this is not you're case. I think you're not seeing a dictionary, but an object defined from models (as is a entry on the database).
You're storing in dict (don't call that value as dict , you're masking a keyword) a key 'sc' with value variable sc, which is returned from a model. I'm having to guess, because I don't know how this model is. Maybe 'Robert' is stored in the attribute name, id or something similar?
You need to show then the proper attribute, something like
{{ sc.name }}
{{ sc.id }}

Related

How to add extra field data to a form field in Wtforms

I am trying to add extra data to a form field in wtforms.
I have to create a text field which has an associated unit with it (eg - meter/sec). How do I add the meter/sec string to the form field?
Is there any way to pass a dictionary or something to add data to the field that i can access in the template?
There is a not very well known parameter, description= to the field constructor. Though it purports to be for help text, the framework itself doesn't care what you put in there (and indeed doesn't use it anywhere at all, other than passing it along.)
So you could do, for example:
class PhysicsForm(Form):
speed = TextField('Speed', description={'unit': 'meters/sec'})
distance = TextField('Distance', description={'unit': 'kilometers'})
Then you could use it in a jinja-style template something like:
{{ form.speed }} <label>{{ form.speed.description.unit }}</label>
footnote There was no real reason for using a dictionary as the value of description - it was merely to illustrate that you can put nearly any value in there, including containers which can hold many values.

get the initial value of a form field as a string in template

If I have set an initial values for the form which I am passing with the help of kargs.
like this
kwargs['initial'] = initial_data
super(JobAdReplyForm, self).__init__(*args,**kwargs)`
All is well and when I am trying to get the form fields in template, I am getting them using form.field_name with the initial value. Now what I want to do is to get the initial value of a particular field in the template only as a string so that I can print it in template itself.
some thing like form.field_name.initial
As long as you are using django 1.3 or greater you should be able to use
{{ form.field_name.value }} in your template.

Why can't iterate through this list in a Django template

I have a variable from my view that is the output of a Model.objects.all() call on that Model. I'm passing it to my template in my view, and I'm trying to iterate over it in the template. I can access the first element of it simply by this line of code. 'code' is the name of a field in my django model. This line does print the first element's 'code' attribute correctly.
{{ var_name.0.code }}
However, when I try to iterate over var_name in a template for loop, nothing shows up. I tried the following code:
{% for single_var in var_name %}
{{ single_var.code }}
{% endfor %}
This isn't actually what I want to do in the for loop, but getting this to work will let me do what I need in the template. It may be noteworthy to add that at the moment this list has only one element in it.
This is for a work project, so that's why I changed the variable names to something generic.
I found that changing the name of single_var to something without an underscore seemed to fix it. This doesn't make a lot of sense to me because the Django template language documentation states the following:
Variable names consist of any combination of alphanumeric characters and the underscore ("_").
Does anyone know why this seemed to fix the problem?

Python / Django - Form Selection Value is Object Id... Can't Get Object

I have a form select box that has values corresponding to objects. The user selects an input and the form submits. I then want to take that value and retrieve the object that has an ID equivalent to the selected form value. However, when I try to do so, I'm getting an error like so:
int() argument must be a string or a number, not 'Cars'
Example:
if form.is_valid():
car = Car.objects.get(id=form.cleaned_data['id'])
I'm guessing the problem is that the returned value is a string and NOT an integer. In PHP this is SIMPLE. How do I typecast or use the returned form value to get an associated object?
Seems as though Django is not returning the value of the form element, but instead the user visible option name...
Form Class:
class CarForm(forms.ModelForm):
class Meta:
model = Car
Html Form:
<form action="">
<select name="id">
{% for car in cars %}
<option value="{{car.id}}">{{car.title}}</option>
{% endfor %}
</select>
</form>
The id field has to be an integer, or a string that can be converted to an integer.
Simple as that!
Somehow, your form.cleaned_data['id'] is returning a model called Cars
Ensure it returns a number if you want to pass it into get(id=
You can use ModelChoiceField instead of generating the select using HTML
in forms.py:
class CarSelectForm(forms.Form):
car = forms.ModelChoiceField(queryset=Car.objects.all(), empty_label=None)
in view.py:
if form.is_valid():
car = form.cleaned_data['car']
This is maybe a bad, but I think working answer. If anyone has a real solution, please post because I still need it.
(I'm using a modelformset, but just a modelform may work the same)
For me, the {{ form.id }} works on the page (puts the id) and comes back correctly in the POST data. However, somewhere along the line it gets converted (as Yuji said in his post) into the model object represented by that id and that is what is in cleaned_data.
In short, change
car = Car.objects.get(id=form.cleaned_data['id'])
to
car = form.cleaned_data['id']
I think it just looks like a string just because when you print or debug, it's using your str or unicode representation.
Repeat: This is almost certainly a side effect or bad way to do things. If I figure out a better way, I'll post it.
I have the same issue... so I tried the following:
ts_1 = form.cleaned_data['lista_trabajos']
ts_2 = request.POST['lista_trabajos']
print(ts_1) # this returns what user sees, ex: 1 - folders
print(ts_2) # this returns value from that option, in my case: 1
Unfortunately, I have been reading that by using raw POST data is not recommended. At the moment, I cannot figure out how to validate and get the raw POST data by using something similar to "clean_data".
You can read about this in: https://books.google.com.ar/books?id=8sU7DwAAQBAJ&pg=PA229&lpg=PA229&dq=form+cleaned_data+to+get+raw+post+data&source=bl&ots=RN9WKRaGJs&sig=QpSoPdI9YSHSNk0zAQIO8phSbOw&hl=es&sa=X&ved=0ahUKEwiBouHattnaAhULFZAKHUKmA4QQ6AEIRzAD#v=onepage&q=form%20cleaned_data%20to%20get%20raw%20post%20data&f=false

Django template can't loop defaultdict

import collections
data = [
{'firstname': 'John', 'lastname': 'Smith'},
{'firstname': 'Samantha', 'lastname': 'Smith'},
{'firstname': 'shawn', 'lastname': 'Spencer'},
]
new_data = collections.defaultdict(list)
for d in data:
new_data[d['lastname']].append(d['firstname'])
print new_data
Here's the output:
defaultdict(<type 'list'>, {'Smith': ['John', 'Samantha'], 'Spencer': ['shawn']})
and here's the template:
{% for lastname, firstname in data.items %}
<h1> {{ lastname }} </h1>
<p> {{ firstname|join:", " }} </p>
{% endfor %}
But the loop in my template doesn't work. Nothing shows up. It doesn't even give me an error. How can i fix this? It's supposed to show the lastname along with the firstname, something like this:
<h1> Smith </h1>
<p> John, Samantha </p>
<h1> Spencer </h1>
<p> shawn </p>
You can avoid the copy to a new dict by disabling the defaulting feature of defaultdict once you are done inserting new values:
new_data.default_factory = None
Explanation
The template variable resolution algorithm in Django will attempt to resolve new_data.items as new_data['items'] first, which resolves to an empty list when using defaultdict(list).
To disable the defaulting to an empty list and have Django fail on new_data['items'] then continue the resolution attempts until calling new_data.items(), the default_factory attribute of defaultdict can be set to None.
try:
dict(new_data)
and in Python 2 it is better to use iteritems instead of items :)
Since the "problem" still exist years later and is inherint to the way Django templates work, I prefer writing a new answer giving the full details of why this behaviour is kept as-is.
How-to fix the bug
First, the solution is to cast the defaultdict into a dict before passing it to the template context:
context = {
'data': dict(new_data)
}
You should not use defaultdict objects in template context in Django.
But why?
The reason behind this "bug" is detailed in the following Django issue #16335:
Indeed, it boils down to the fact that the template language uses the same syntax for dictionary and attribute lookups.
... and from the docs:
Dictionary lookup, attribute lookup and list-index lookups are implemented with a dot notation. [...] If a variable resolves to a callable, the template system will call it with no arguments and use its result instead of the callable.
When Django resolve your template expression it will try first data['items']. BUT, this is a valid expression, which will automatically creates a new entry items in your defaultdict data, initialized with an empty list (in the original author case) and returns the list created (empty).
The intented action would be to call the method items with no arguments of the instance data (in short: data.items()), but since data['items'] was a valid expression, Django stop there and gets the empty list just created.
If you try the same code but with data = defaultdict(int), you would get a TypeError: 'int' object is not iterable, because Django won't be able to iterate over the "0" value returned by the creation of the new entry of the defaultdict.

Categories

Resources