Checking for widget attribute in Django templates - django

I'd need to pass some data from my manually generated form to the template, and would need to check the presence of that information there.
I'm generating my form as such (in the __init__ part):
for i in days_in_month:
self.fields["info_%s" % i] = forms.ChoiceField(label="%s" % i.strftime("%a %d-%m-%Y"),
required=False,
choices=Information._meta.get_field('info').choices,
widget=forms.Select(attrs={'something': 'test'}))
What I would like to do, is to check in the template whether the attribute something is set, and if so, display its value (in the example above: test).
Any idea?
I tried with {{ field.attribute }} as per Access form field attributes in templated Django and the below:
{% for field in form %}
{{ field.label_tag }} {{ field }}
{{ field.widget.attrs.something }}
{% endfor %}
... but that doesn't work (invalid).
Ultimately I want to do something similar to:
{% if field.widget.attrs.something %}{{ field.widget.attrs.something }}{% endif %}

That would be
{{ field.field.widget.attrs.something }}

Related

Get formset name variables in django templates

I am sending a formset to my template. I want to add some style to it, so I need to access his variables.
I took the following code from documentation, where they print the form and it has some attributes, amongside them the name="form-0-title".
for form in formset:
print(form.as_table())
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title"></td></tr>
...
As I want to style my forms, I need to give the inputs a name to know how to treat them in the backend. When I do the following in the templates
{{ proficiency_form.management_form }}
{% for form in proficiency_form %}
{{form.title.name}}
{% endfor %}
I get title, title, ... instead of id_form-0-title, id_form-1-title, ...
How can I get the correct name in the templates?
You can easily get the input's name of your fields like so:
{{ proficiency_form.management_form }}
{% for form in proficiency_form %}
{{form.title.html_name}}
{% endfor %}
If you want to get the label's id, you can consider this approach:
{{ proficiency_form.management_form }}
{% for form in proficiency_form %}
{{form.title.id_for_label}}
{% endfor %}
Read more about it in the official Docs.
You can find a similar(almost duplicate) question here.

Django: How to get selected text of DropDown in Template?

In the template I get the whole DropDown correctly shown with something like this:
{{form.deal_type}}
But what if I wanted just the text of the selected dropdown shown?
This shows me just a foreignkey.
{{form.deal_type.value}}
I don't know why you want to do this exactly, but try this.
TO LOOP:
{% for value, text in form.deal_type.field.choices %}
{{ value }}: {{ text }}
{% if value == form.deal_type.value %}
<strong>{{ text }}</strong> <!-- THIS IS THE SELECTED ONE... -->
{% endif %}
{% endfor %}
EDIT:
I meant the above code as an illustration, not that you should use it verbatim. This code will do more like what you want.
{{ form.deal_type.label_tag }}
{% for value, text in form.deal_type.field.choices %}
{% if value == form.deal_type.value %}
{{ text }}
<input type="hidden" name="deal_type" value="{{ value }}" />
{% endif %}
{% endfor %}
I had a similar issue. To solve it I just passed the value to the template directly from the view. So in your view you presumably have something in the way of
data = {'form' :form,}
return render_to_response('destination.html', data, context_instance = RequestContext)
In data you are passing the form that includes deal_type. Add to
data a variable deal_type set equal to Object.deal_type.display_value with
data = {'form' :form,}
if Object.deal_type: data['deal_type'] = Object.deal_type.display_value
return render_to_response('destination.html', data, context_instance = RequestContext)
Then on your template you can just use
{% if condition_to_show_just_text %}
{{deal_type}} {{form.deal_type.as_hidden}}
{% else %}
{{form.deal_type}}
{% endif %}
It may be insiginificant in this case, but it seemed to me that if the list was long, iterating with the for loop on the template would be less efficient than pulling directly from the object

Control the form errors display while using {{ form.as_ul }} in Django templates.

I like the convenient output form method {{ form.as_ul }} but is there a way I can still continue to use it but capture all the errors upfront instead of displaying the error just above each field.
I understand that there are ways to loop through each form element and so on as mentioned in django docs but I want to continue to utilize the capability of form.as_ul() except get control over error display.
Solved this problem by using Reusable Form Templates.
Its simple...
Create a reusable template with the following code snippets based on your need.
If you want to display all errors right at the top of the form...
{% if form %}
{% if form.errors %}
{% for field in form %}
{{field.errors}}
{% endfor %}
{% endif %}
{% for field in form %}
<li>{{ field.label_tag }}: {{ field }}</li>
{% endfor %}
{% endif %}
If you want to display all errors right after each form field without the default html elements around error use...
{% for field in form %}
{{ field.label_tag }}: {{ field }}
{% for error in field.errors %}{{ error }}{% endfor %}
{% endfor %}
Used the second template and created a Inclusion Tag
The only way I see is to inherit the new form class from forms.Form and alter as_ul method as you like. Which isn't very good if you are going to use third-party forms like login form and so on (they won't have this method).
I think the best solution is to create your own inclusion tag and render form with it. It will be as short as as_ul ({% render_form form %}) but very flexible, it will work with all forms and won't mix HTML and Python code.
I still think the customization for rendering form in templates is quite flexible. I usually do this for my webapps. You may work with a bit javascript and css but not a big problem. Moreover, I think we should try to make the app simple.

django templates accessing a dict value based on key

in my views.py i obtain 5 dicts, which all are something like {date:value}
all 5 dicts have the same length and in my template i want to obtain some urls based on these dicts, with the common field being the date - as you would do in an sql query when joining 5 tables based on a common column
in python you would do something like:
for key, value in loc.items():
print key, loc[key], ctg[key], sctg[key], title[key], id[key]
but in django templates all i could come up with is this:
{% for lock, locv in loc.items %}
{% for ctgk, ctgv in ctg.items %}
{% for subctgk, subctgv in subctg.items %}
{% for titlek, titlev in titlu.items %}
{% for idk, idv in id.items %}
{% ifequal lock ctgk %}
{% ifequal ctgk subctgk %}
{% ifequal subctgk titlek %}
{% ifequal titlek idk %}
<br />{{ lock|date:"d b H:i" }} - {{ locv }} - {{ ctgv }} - {{ subctgv }} - {{ titlev }} - {{idv }}
.... {% endifequals & endfors %}
which of course is ugly and takes a lot of time to be rendered
right now i am looking into building a custom tag, but i was wondering if you guys have any feedback on this topic?
Sounds to me like you need to use something other than aligned dicts. How about a dict of a small class, which contains the things you want:
class MyThing:
def __init__(self, loc, ctg, sctg, title, id):
self.loc = loc
self.ctg = ctg
self.sctg = sctg
self.title = title
self.id = id
Would that make your template code a bit less painful? (Apologies if I've misunderstood the problem - I'm having a hard time following your nested ifs!).
Django templates should try to resolve variables with dot as a dictionary lookup (if varaible is an dictionary). So ctg.key equals to ctg[key]. Did you try this:
{% for key, value in loc.items %}
{{ key|date:"d b H:i" }} - {{ value }} - {{ ctg.key }} - {{ subctg.key }} - {{ title.key }} - {{ id.key }}

django templates question

How can I get the value of form.field in template. I mean not the html input element of the field but the value inside the input?
To get the bound data (in 1.2.3)
{{ form.field.data }}
In the development version, it's {{ form.field.value }} which automatically pulls initial data OR bound data whereas it's an explicit call in the current release:
form.field.field.initial or form.field.data
Update: the admin forms work differently. First of all, the BoundField is {{ adminfield.field }} and not {{ adminfield }} in your comment, but we have bigger problems.
On the change form, the form is not bound so data can only be pulled from the initial dictionary passed into the form constructor. It's not accessible via the django template syntax.
Here's the relevant lines in BoundField:
if not self.form.is_bound:
data = self.form.initial.get(self.name, self.field.initial)
# you can't do this kind of lookup from the template.
The only way to access this type of info from the template without making a template tag (which you should!) is to loop through each key/value in the initial dictionary and comparing to the current fields name.
{% for line in fieldset %}
{% for adminfield in line %}
{% for k, v in adminfield.field.form.initial.items %}
{% if k == adminfield.field.name %}
{{ k }}:{{ v }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}