I've been doing some custom forms with django but I don't get how to access attributes that a specific form field has attached via the forms.py.
def putErrorInTitle (cls):
init = cls.__init__
def __init__ (self, *args, **kwargs):
init(self, *args, **kwargs)
if self.errors:
for field_error in self.errors:
self.fields[field_error].widget.attrs['title'] = self.errors[field_error][0]
self.fields[field_error].widget.attrs['class'] = "help_text error_field"
cls.__init__ = __init__
return cls
That's how I attached the attibutes to the field.
<dl class="clearfix two">
<dd>
<label for="id_diagnosis">Diagnostico:</label>
<select class="{{form.id_diagnosis.class}}" id="id_equipment_activity-{{ forloop.counter0 }}-id_diagnosis" name="equipment_activity-{{ forloop.counter0 }}-id_diagnosis">
{% for x,y in form.fields.id_diagnosis.choices %}
<option value="{{ x }}" {% ifequal form.id_diagnosis.data|floatformat x|floatformat %}selected="selected"{% endifequal %}>{{ y }}</option>
{% endfor %}
<option value="1000" {% ifequal form.id_diagnosis.data|floatformat '1000'|floatformat %}selected="selected"{% endifequal %}>Otro</option>
</select>
</dd>
<dd class="vertical_center" id="optional_diagnosis"><label for="optional_diagnosis">Diagnostico opcional:</label>{{ form.optional_diagnosis }}</dd>
</dl>
I've been trying to access its attributes:
class="{{form.id_diagnosis.class}}", class="{{form.id_diagnosis.widget.class}}"
And I don't seem to find clear documentation about what's accessible and what's not. Really I would rather have old fashion documentation than django "friendly" one
In other cases it can can be useful to set and get field attributes.
Setting in form's init function:
self.fields['some_field'].widget.attrs['readonly'] = True
... and accessing it in a template:
{{ form.some_field.field.widget.attrs.readonly }}
It looks like you just want to display form errors for each field.
After the form is cleaned or validated in the view, the fields should contain
the error messages. So that you can display them in the template like so:
<form action='.' method='post'>
...
<div class='a-field'>
{{ form.field_1.errors|join:", " }}
{{ form.field_1.label_tag }}
{{ form.field_1 }}
</div>
...
</form>
If however you really want to display the form field attributes then you
can try something like:
{{ form.field_1.field.widget.attrs.maxlength }}
The above answers are correct, however, I'd like to add a note for those who are accessing form fields in a loop.
If you're doing this in a loop like this
{% for field in form %}
{{ field.field.widget.attrs.placeholder }} # field.field is the key here
{% endfor %}
Related
I am struggling to see a way to style a django form in the style of a uikit horizontal form. UIKit has the styling I want and Django has the validation and templating I want.A way to implement a datepicker too would be useful.
I have tried the plain django form template with .as_p and .as_table. I have also tried to use Meta and widgets but couldn't get that to work. I can't see how I can add the needed uikit tags to each element and add the uk-form-controls div.
template.html
<form class="uk-form-horizontal uk-margin-large uk-align-center">
<div class="uk-margin">
<label class="uk-form-label" for="form-horizontal-text">Job Title</label>
<div class="uk-form-controls">
<input class="uk-input uk-form-width-large" id="form-horizontal-text" type="text" placeholder="Some text...">
</div>
</div>
forms.py
class job_form(forms.Form):
job_title = forms.CharField(label='Job Title', max_length=50)
hiring_manager = forms.CharField(label='Hiring Manager', max_length=50)
job_description = forms.CharField(label='Job Description', max_length=50)
salary = forms.IntegerField()
closing_date = forms.DateField()
I am expecting to be able to have the uikit form styling with the templating and validation of django forms but am yet to get it to work.
Django has a variety of ways to override the form behavior and layout. I see you are using forms.Form instance. Simply add your classes to the form class like:
class NiceForm(forms.Form):
solid_field=forms.CharField(widget=forms.TextInput(attrs={'class': 'uk-form-input'}))
Although it is simple, but sluggish, when you want introduce breaking changes to the layout, I would override the template (or render method if you like) to bundle a reusable widget. Simple example to extract the form to external reusable template as you can render them manually as HTML like documentation.
Leave the form clean and use templatetag to override classes:
# _form_icludes.html
{% for field in form.visible_fields %}
<fieldset class="uk-fieldset">
<div class="uk-margin">
<label class="uk-form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="uk-form-controls">
{% if field.field.widget.input_type == 'select' %}
{{ field | add_css_cls:'uk-select'}}
{% elif field.field.widget.input_type == 'option'%}
{{ field | add_css_cls:'uk-option'}}
{% elif field.field.widget.input_type == 'checkbox'%}
{{ field | add_css_cls:'uk-checkbox'}}
{% elif field.field.widget.input_type == 'select'%}
{{ field | add_css_cls:'uk-select'}}
{% elif field.field.widget.input_type == 'file'%}
{{ field }}
{% else %}
{{ field | add_css_cls:'uk-input'}}
{% endif %}
{% if field.help_text %}
<span class="uk-text-small uk-text-left uk-text-italic">
{{ field.help_text }}
</span>
{% endif %}
{% if field.errors %}
{% for error in field.errors %}
<p class="uk-flex uk-flex-middle uk-text-danger ">
<span data-uk-icon="icon:warning" class="uk-text-danger uk-margin-small-right"></span>
{{ error | escape }}
<p/>
</div>
{% endfor %}
{% endif %}
</div>
</fieldset>
{% endfor %}
# add_css_cls
from django import template
register = template.Library()
#register.filter
def add_css_cls(value, arg):
css_classes = value.field.widget.attrs.get('class', '').split(' ')
if css_classes and arg not in css_classes:
css_classes = '%s %s' % (css_classes, arg)
return value.as_widget(attrs={'class': css_classes})
There are many different ways.
I have a tuple which holds multiple color and their codes:
color_list = (
('#CD5C5C', 'Indian Red'),
('#F08080', 'Light Coral'),
('#FA8072', 'Salmon'),
................
)
and this is the model:
class ColorList(models.Model):
color = models.CharField(choices=color_list, max_length=10)
class Product(models.Model):
color_list = models.ManyToManyField(ColorList)
view:
def product_edit(request, pk):
product = get_object_or_404(Product.objects.prefetch_related('color_list'), pk=pk)
context = {'product': product,'color_list': color_list}
return render(request, 'admin/product/product_edit.html', context)
Now I want to edit previously saved data in template using a form:
<div class="form-group">
<label><strong>Color List</strong></label>
<select name="color_list" class="form-control selectpicker" multiple data-live-search="true" >
{% for key, value in color_list %}
{% for pro_color in product.color_list.all %}
<option value="{{ key }}" {% if pro_color.color == key %} selected {% endif %}>
{{ value }}
</option>
{% endfor %}
{% endfor %}
</select>
</div>
I want to show previously selected color with other color options, but using this template code, it generating multiple duplicate <options>. So the problem is how can I use multiple for loop in template with preselected color <options> ?
The reason your colors are duplicating is because you nested two loops unnecessarily to get the key/value pairs. You can use .get_FOO_display() instead.
<div class="form-group">
<label><strong>Color List</strong></label>
<select name="color_list" class="form-control selectpicker" multiple data-live-search="true" >
{% for pro_color in product.color_list.all %}
<option value="{{ pro_color.get_color_display }}" {% if pro_color.color == color_list.color %} selected {% endif %}>
{{ pro_color.color }}
</option>
{% endfor %}
</select>
</div>
https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_FOO_display
For Edit Related Issues, Refer Template of Django Admin > Edit User
Probable url will be: http://localhost:8000/admin/auth/user/{id}/change/
Here They Have Permissions column which is Select Many and it ofcause retains its value on refresh too.
I created a model and one of the fields has choices. I created a select form in my template and the choices are not been displayed. I'm not using Forms or ModelForms for a few reasons. But my understanding is that I should be able to make this work using CHOICES in the model, building a form in the template and save the information using the object manager. How can I get the choices to populate the form?
Models.py
class NewRating(models.Model):
EXCELLENT = 'EX'
GOOD = 'GD'
FAIR = 'FR'
BAD = 'BD'
RATING_CHOICES = (
(EXCELLENT, 'Excellent'),
(GOOD, 'Good'),
(FAIR, 'Fair'),
(BAD, 'Bad')
)
function = models.ForeignKey(Function, related_name='frating')
timeline = models.ForeignKey(Timeline, related_name='trating')
rating = models.CharField(max_length=25,choices=RATING_CHOICES)
Views.py
def f_page(request, Function_id):
assignments = Function.objects.get(id=Function_id)
time = Timeline.objects.all()
ratings = NewRating.objects.all()
context = {
'assignments': assignments,
'time' : time,
'ratings' : ratings,
}
return render (request, 'project/pager.html', context)
HTML
<div id=for_rat>
{% for rated in time %}
<form action= "/project/rated" method='POST'>
{% csrf_token %}
{{rated.segment}}
<input type="hidden" name="year" value="{{rated.year}}">
<input type="hidden" name="month" value= "{{assignments.id}}">
<select name="ratings">
<option value="">Choose From List</option>
{% for rating in ratings %}
<option value="{{rating.choices}}">{{rating.choices}}</option>
{% endfor %}
</select>
{% endfor %}
<input type="submit" value="Save">
</form>
</div>
Using {% for rating in ratings %}
{{rating.choices}}
{% endfor %} is not working. Can I set the choices in the models if I'm building my own forms? If yes, what am I doing wrong that this is not rendering?
Easiest, simplest and the 100% working method is:
Get the objects [lets say 'my_Model_with_choices'] with my_Model_with_choices = yourModel.objects.first() and you can get the choices with my_Model_with_choices._meta.get_field('your_foreign_key_variable_name').choices
def f_page(request, Function_id):
assignments = Function.objects.get(id=Function_id)
ratings = NewRating.RATING_CHOICES
context = {
'ratings' : ratings,
}
return render (request, 'project/pager.html', context)
Inside HTML template:
<select class="custom-select col-md-5" name="ratings" id="ratings" required>
<option disabled selected value="">Ethnic Group</option>
{% for value, ratings_group in ratings %}
<option value='{{value}}'>{{ratings_group}}</option>
{% endfor %}
</select>
If you're strictly not willing to use Form or ModelForm, you need to have choices to be iterable which is possible via enum.
You can check my sample code about how to implement choices with enums here.
You'll have to make some tweaks to your context and template after doing this.
You might want to look how to get the list of choices with enum.
try this
{% for rating in ratings %}
<select name="ratings">
<option value="">Choose From List</option>
{% for x, y in rating._meta.get_field('rating').choices %}
<option value="{{ x }}">{% if rating.rating == x %} selected{% endif %}>
{{ y }}
</option>
{% endfor %}
</select>
{% endfor %}
Make sure that this code is outside the
{% for rated in time %}
...
{% endfor %}
block
I have a simple form which uses a SessionWizardView to spread it over a number of pages. Below is an example of one of the questions.
first_name = forms.CharField(max_length=100, label='What is your first name?', error_messages={'required': 'Please enter your first name'})
Which renders out as
<label for="id_0-first_name">What is your first Name?</label>
<ul class="errorlist">
<li>Please enter your first name</li>
</ul>
<input id="id_0-first_name" maxlength="100" name="0-first_name" type="text" />
Can anyone tell me hwo to change the error output so that it is in <p> Paragraph </p> format rather than <li> List item </li> format?
I am using Django 1.6.2
You'll have to create a class that does renders the HTML as you would want it. See the docs here.
The example from the docs:
from django.forms.util import ErrorList
class DivErrorList(ErrorList):
def __unicode__(self):
return self.as_divs()
def as_divs(self):
if not self: return u''
return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self])
f = ContactForm(data, auto_id=False, error_class=DivErrorList)
f.as_p()
You can do as #schillingt suggested and create your own error list class.
Or, if you want to handle this in your template, you can use something like:
<form method="post" action="/some-view/">
... other fields, etc. omitted ...
<!-- The label and form field -->
{{ form.first_name.label_tag }}
{{ form.first_name }}
<!-- Output any errors -->
{% for error in form.first_name.errors %}
<p>{{ error }}</p>
{% endfor %}
... other fields, etc. omitted ...
<button type="submit">Submit</button>
</form>
Update
In order to do this in a cleanly repeatable way, make a template named form-field.html:
{{ field.label_tag }}
{{ field }}
<!-- Output any errors -->
{% for error in field.errors %}
<p>{{ error }}</p>
{% endfor %}
Then, update your main template:
<form method="post" action="/some-view/">
... other fields, etc. omitted ...
{% with field=form.first_name %}
{% include "form-field.html" %}
{% endwith %}
... other fields, etc. omitted ...
<button type="submit">Submit</button>
</form>
You can then make updates to the single form-field.html template and update all of your forms, and it makes your main template a bit simpler
I have something like this:
forms.py:
AVATAR_CHOICES = (('1','option1'), ('2','option2'), ('3','option3'),
('4','option4'))
class RegistrationForm(forms.Form):
avatar = ChoiceField(widget=RadioSelect, choices=AVATAR_CHOICES)
I'm passing form from my view:
views.py
form = RegistrationForm()
return render_to_response('registration/register.html', {'form': form},
context_instance=RequestContext(request))
into a template like this:
registration.html:
{% for radio in form.avatar %}
<label class="radio">{{ radio.tag }}</label>
{% endfor %}
but I'd like to include images in front of these option fields as a way to let the users choose an avatar. However, I don't know how to access keys or values from the tuple AVATAR_CHOICES. The main idea is to be able to do something like this:
{% for radio in form.avatar %}
<label class="radio">{{ radio.tag }}</label>
<img src="{{ STATIC_URL }}img/avatars/{{ radio.tag.value }}.jpg"/>
{% endfor %}
How can I do this?
Thanks in advance.
You could try
{{ radio.choice_value }}{# value of the choice of the current input #}
{{ radio.choice_label }}{# label of the choice of the current input #}
{{ radio.choice_index }}{# 0-based index #}
Only choice_label gets documented, but you could safely use it so far.