I'm looking at a package called crispy forms I was wondering if it was possible to change the html name from within the template?
i.e.
{{ form.username|changename }}
Rules:
I don't want to change the original form or view (at all), I only have access to the template.
Since you're changing the label, I suggest you do it template-ish, without using a templatetag or a filter:
<label for="id_username">Your label name here:</label>
{{ form.username }}
Or, if you can't resist, you have to apply a filter to your field.label property:
{{ form.username.label|my_custom_filter }}
A simple filter could be:
#register.filter(name='my_custom_filter')
def my_custom_filter(value):
# here value is the value of your label
# process it as you please then return the new value
if value == 'changeme':
return 'changed label'
return value
This is just an example to show you how a template filter works, you have then to elaborate it and change name, logic etc etc
This could be over simplifying it, but what not just raw output it?
<label for="">what ever you want</label>
<input type="text" name="{{ form.username.html_name }}" id="{{ form.username.auto_id }}">
I would still do this in the form.py myself but if all you have is the template to work with then it does not need anything fancy here.
Related
in forms.py
class PlaceOrder(forms.ModelForm):
class Meta:
model = Order
fields = ["Product_ID","HowMany","DateSubmit",]
to call a form i usually use
{{ Form }}
that will render the form automatically
but is it possible to make it manually?
for example i want the form to be exactly like this
<input id="Product_ID" type="hidden" value="{{ Product.PId }}" >
<input id="HowMany" type="text">
<input id="DateSubmit" type="hidden" value="{{ date }}" >
i have tried wrapping them in
{% for field in form %}
but it gave the wrong output
Sorry if this is confusing
but i don't really know how to explain it,
i am still new to Django
You should be able to access individual fields in the form using something like
{{Form.Product_ID}}
which will give you the Product_ID field widget.
Now if you want to access the already pre-filled data you should be able to do so with
{{Form.Product_ID.label}}
or
{{Form.Product_ID.value}}
Also check:
https://docs.djangoproject.com/en/dev/topics/forms/#looping-over-the-form-s-fields
To get some more control over my input fields, I try to "copy" the function that generates input fields in the template
I use a ModelForm and I want to change
...
{{ form.name }}
...
into something like
...
<input id="{{ form.name.auto_id }}" type="text" name="{{ form.name.name }}" maxlength="{{ form.name.**get_max_length** }}" value="{{ form.name.**get_value_or_initial_value** }}"/>
...
Most of that works already, except maxlength and value.
maxlength
I read
How can I programmatically obtain the max_length of a Django model field?
Django: model maxlength and form maxlength
but I still don't get it right...
value
The answer to this question (How can you manually render a form field with its initial value set?) points to a ticket which is fixed already. Still name.value would print "None" if there is no value present. Am I meant to catch value="None" manually or is there a better solution meanwhile?
[edit]
value seems to work like that
{{ form.name.value|default_if_none:"" }}
(from Display value of a django form field in a template?)
You can get the max_length attribute from the widget. For the initial value, you only need to access the value attribute, there is already an initial or submitted value. All initial values passed to form class are held in form.initial, but you probably don't need to check these values:.
<input id="{{ form.name.auto_id }}" type="text" name="{{ form.name.name }}" maxlength="{{ form.name.field.widget.attrs.max_length }}" value="{% if form.name.value %}{{ form.name.value }}{% endif %}"/>
I wish to edit ini files over web server, decided to use django, been using it for few days now. I can't figure out how to accomplish this. I have ini file structure looking like this:
{'GROUP', {PROPERTY : VALUE}}
Example when I read this kind of ini file:
[LOG]
FilePath = C:/Log
[CMD]
Level = 5
I will get my data structure filled like this:
{'LOG', {'FilePath' : 'C:/Log',},
{'CMD', {'Level', '5'}}}
Loop looks like this:
for group in settingsDict:
print group # group
for property in settingsDict[group]:
print property , # property
print settingsDict[group][property] # value
I am using ini file parser.
I am having trouble understanding how to correctly develop in django: views.py is some kind of controller for django and templates are views and model would be my ini file (probably linked with db using django model), or am I getting something wrong?
I have no problem passing this dictionary to template, making a for loop in it and creating html tags like: <input type="text" name={{ property }} value={{ value }} maxlength="100" />. But how do I then post all the edited values back to control to save them in file (or db)? I Would need all 3 values, that is GROUP, PROPERTY and VALUE.
Then I discovered django also has html widgets, which you create in views.py and then pass it to template. But this is where I stop understanding things, since I am creating widget in my controller class, but even if I am.
Shall I create a list of all django widgets and pass it to template? Same question occurs, how do I get all the widget values back to controller (views.py)?
Update (11.6.2012):
My code looks like this:
views.py
class DynForm(forms.Form):
def setFields(self, kwds):
keys = kwds.keys()
keys.sort()
for k in keys:
self.fields[k] = kwds[k]
def settings(request):
global Settings #my ini dict
kwargs = {}
for group in Settings:
for property in Settings[group]:
kwargs[property] = forms.CharField(label = property, initial = Settings[group][property])
f = DynForm()
f.setFields(kwargs)
return render_to_response('/settings.html',
{
'textWidget' : f,
})
#csrf_exempt
def save(request):
if request.method == 'POST': # If the form has been submitted...
form = DynForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# process form data
# and return response
settings.html
<form action="/save/" method="post">
{% csrf_token %}
{% for field in textWidget %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Save" /></p>
</form>
The problem is, DynForm(request.POST) returns null so I can't get field values. My request.POST is correct, containing all fields and values. As much as I know, I am not suppose to parse request.POST data "by hands"?
OK, finally figured it out, taking me a lot of time (I am lacking a lot of python and django knowledge). I can't paste final solution because of copy right permissions, here is the concept:
Form
class DynamicForm(forms.Form):
def __init__(self,*k,**kw):
forms.Form.__init__(self,*k,**kw)
# loop over data from **kw
# create field
# set field default value
Notes about this code:
If form doesn't use super(SuperForm, self).__init__(*args, **kwargs), you must use forms.Form.__init__(self,*k,**kw) so you can append fields to form using self.fields attribute.
If you need to use default field value, use self.data[field] = defVal not initial = defVal. Form becomes unbound and you won't be able to parse data in your request.POST method. Unbound form (and with errors) will always return is_valid() False.
With this class, you have no problems parsing request.POST data. Looping over dynamic form fields looks like this:
View
for name,field in form.fields.items():
# name - field name
# form.data[name] - field value
Notes:
For the sake of simplisity use #csrf_exempt tag before POST method. See http://jordanmessina.com/2010/05/24/django-1-2-csrf-verification-failed/
Template code loops over fields in form displaying field label and value separated with :
Template
<form action="/Tris/save/" method="post">
{% csrf_token %}
{% for field in textWidget %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.non_field_errors }}
{{ field.label }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Save" /></p>
</form>
Most of the solution is from here: http://jacobian.org/writing/dynamic-form-generation/ and django documentation.
All,
How Can we increment a value like the following in django templates,
{{ flag =0 }}
{% for op in options %}
{{op.choices}}<input type="radio" name="template" id="template" value="template{{flag++}}"/>
{% endfor %}
thanks..
I don't think it's intended you should alter data in your templates. For in your specific case, you could instead use the forloop.counter variable.
For example:
{% for op in options %}
{{op.choices}}<input type="radio" name="template" id="template{{forloop.counter}}" value="template{{forloop.counter}}"/>
{% endfor %}
Also note that I added that number to the id attributes of the <input /> tag. Otherwise you'll have multiple inputs with the same id.
EDIT: I didn't note that it was a radio input. You could of course have the same name for each <input type="radio" />.
You explicitly can't do that in a template. Variable assignment is not allowed.
However if all you want is a counter in your loop, you just need to use {{ forloop.counter }}.
You might also want to look into having Django forms produce these values
When I define a Django form class similar to this:
def class MyForm(forms.Form):
check = forms.BooleanField(required=True, label="Check this")
It expands to HTML that looks like this:
<form action="." id="form" method=POST>
<p><label for="check">Check this:</label> <input type="checkbox" name="check" id="check" /></p>
<p><input type=submit value="Submit"></p>
</form>
I would like the checkbox input element to have a label that follows the checkbox, not the other way around. Is there a way to convince Django to do that?
[Edit]
Thanks for the answer from Jonas - still, while it fixes the issue I asked about (checkbox labels are rendered to the right of the checkbox) it introduces a new problem (all widget labels are rendered to the right of their widgets...)
I'd like to avoid overriding _html_output() since it's obviously not designed for it. The design I would come up with would be to implement a field html output method in the Field classes, override the one for the Boolean field and use that method in _html_output(). Sadly, the Django developers chose to go a different way, and I would like to work within the existing framework as much as possible.
CSS sounds like a decent approach, except that I don't know enough CSS to pull this off or even to decide whether I like this approach or not. Besides, I prefer markup that still resembles the final output, at least in rendering order.
Furthermore, since it can be reasonable to have more than one style sheet for any particular markup, doing this in CSS could mean having to do it multiple times for multiple styles, which pretty much makes CSS the wrong answer.
[Edit]
Seems like I'm answering my own question below. If anyone has a better idea how to do this, don't be shy.
Here's a solution I've come up with (Django v1.1):
{% load myfilters %}
[...]
{% for field in form %}
[...]
{% if field.field.widget|is_checkbox %}
{{ field }}{{ field.label_tag }}
{% else %}
{{ field.label_tag }}{{ field }}
{% endif %}
[...]
{% endfor %}
You'll need to create a custom template tag (in this example in a "myfilters.py" file) containing something like this:
from django import template
from django.forms.fields import CheckboxInput
register = template.Library()
#register.filter(name='is_checkbox')
def is_checkbox(value):
return isinstance(value, CheckboxInput)
More info on custom template tags available here.
Edit: in the spirit of asker's own answer:
Advantages:
No futzing with CSS.
The markup ends up looking the way it's supposed to.
I didn't hack Django internals. (but had to look at quite a bunch)
The template is nice, compact and idiomatic.
The filter code plays nice regardless of the exact values of the labels and input field names.
Disadvantages:
There's probably something somewhere out there that does it better and faster.
Unlikely that the client will be willing to pay for all the time spent on this just to move the label to the right...
I took the answer from romkyns and made it a little more general
def field_type(field, ftype):
try:
t = field.field.widget.__class__.__name__
return t.lower() == ftype
except:
pass
return False
This way you can check the widget type directly with a string
{% if field|field_type:'checkboxinput' %}
<label>{{ field }} {{ field.label }}</label>
{% else %}
<label> {{ field.label }} </label> {{ field }}
{% endif %}
All presented solutions involve template modifications, which are in general rather inefficient concerning performance. Here's a custom widget that does the job:
from django import forms
from django.forms.fields import BooleanField
from django.forms.util import flatatt
from django.utils.encoding import force_text
from django.utils.html import format_html
from django.utils.translation import ugettext as _
class PrettyCheckboxWidget(forms.widgets.CheckboxInput):
def render(self, name, value, attrs=None):
final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
if self.check_test(value):
final_attrs['checked'] = 'checked'
if not (value is True or value is False or value is None or value == ''):
final_attrs['value'] = force_text(value)
if 'prettycheckbox-label' in final_attrs:
label = _(final_attrs.pop('prettycheckbox-label'))
else:
label = ''
return format_html('<label for="{0}"><input{1} /> {2}</label>', attrs['id'], flatatt(final_attrs), label)
class PrettyCheckboxField(BooleanField):
widget = PrettyCheckboxWidget
def __init__(self, *args, **kwargs):
if kwargs['label']:
kwargs['widget'].attrs['prettycheckbox-label'] = kwargs['label']
kwargs['label'] = ''
super(PrettyCheckboxField, self).__init__(*args, **kwargs)
# usage in form
class MyForm(forms.Form):
my_boolean = PrettyCheckboxField(label=_('Some label'), widget=PrettyCheckboxWidget())
I have PrettyCheckboxWidget and PrettyCheckboxField in an extra file, so they may be imported where needed. If you don't need translations, you can remove the ugettext parts. This code works on Django 1.5 and is untested for lower versions.
Advantages:
Highly performant, needs no template modifications
Easy to use as a custom widget
Disadvantages:
"as_table" renders the checkbox + label inside the second column
{{ field.label }} inside the template is empty. The label is instead bound to {{ field }}
More work than I planned on doing on a Saturday ;-)
I know that the user excluded CSS, but considering the top answers take about half hour of work to do such a small thing, but knowing that details like these are important on a website, I'd settle for the CSS solution.
checkbox.css
input[type="checkbox"] {
float: left;
margin-right: 10px;
margin-top: 4px;
}
forms.py
class MyForm(forms.ModelForm):
# ...
class Media:
css = {
'all': 'checkbox.css',
}
template.html
{{ form.media }}
{{ form.as_p }}
Advantages:
fast!
no futzing with template tags (just form.as_p)
no new damned widgets
the CSS file is automatically included in every form
Disadvantages:
the HTML doesn't reflect the presentation (but is good enough!)
your frontendist could complain
Here's what I ended up doing. I wrote a custom template stringfilter to switch the tags around. Now, my template code looks like this:
{% load pretty_forms %}
<form action="." method="POST">
{{ form.as_p|pretty_checkbox }}
<p><input type="submit" value="Submit"></p>
</form>
The only difference from a plain Django template is the addition of the {% load %} template tag and the pretty_checkbox filter.
Here's a functional but ugly implementation of pretty_checkbox - this code doesn't have any error handling, it assumes that the Django generated attributes are formatted in a very specific way, and it would be a bad idea to use anything like this in your code:
from django import template
from django.template.defaultfilters import stringfilter
import logging
register=template.Library()
#register.filter(name='pretty_checkbox')
#stringfilter
def pretty_checkbox(value):
# Iterate over the HTML fragment, extract <label> and <input> tags, and
# switch the order of the pairs where the input type is "checkbox".
scratch = value
output = ''
try:
while True:
ls = scratch.find('<label')
if ls > -1:
le = scratch.find('</label>')
ins = scratch.find('<input')
ine = scratch.find('/>', ins)
# Check whether we're dealing with a checkbox:
if scratch[ins:ine+2].find(' type="checkbox" ')>-1:
# Switch the tags
output += scratch[:ls]
output += scratch[ins:ine+2]
output += scratch[ls:le-1]+scratch[le:le+8]
else:
output += scratch[:ine+2]
scratch = scratch[ine+2:]
else:
output += scratch
break
except:
logging.error("pretty_checkbox caught an exception")
return output
pretty_checkbox scans its string argument, finds pairs of <label> and <input> tags, and switches them around if the <input> tag's type is "checkbox". It also strips the last character of the label, which happens to be the ':' character.
Advantages:
No futzing with CSS.
The markup ends up looking the way it's supposed to.
I didn't hack Django internals.
The template is nice, compact and idiomatic.
Disadvantages:
The filter code needs to be tested for exciting values of the labels and input field names.
There's probably something somewhere out there that does it better and faster.
More work than I planned on doing on a Saturday.
Changing checkbox position in Django admin can be quite tricky, but luckily there is a simple solution using custom widget:
from django.forms.widgets import Widget, CheckboxInput, boolean_check
class RightCheckbox(Widget):
render = CheckboxInput().render
def __init__(self, attrs=None, check_test=None):
super(RightCheckbox, self).__init__(attrs)
self.check_test = boolean_check if check_test is None else check_test
Django uses left position only when widget is subclass of CheckboxInput
Order of inputs and labels is provided via normal_row parameter of the form and there are no different row patterns for checkboxes. So there are two ways to do this (in 0.96 version exactly):
1. override _html_output of the form
2. use CSS to change position of the label and checkbox