As part of my models, I have an IntergerField "choices".
These choices have been labelled. (Label 1 = Straw, Label 2 = Yellow...)
However, the HTML renders the integer rather than the actual labels.
What do I need to do return the labels and not the field's interger?
Is it somethng I need to do in views? Or do I address it directly in the html file?
Code below:
Models
CHOICE1=(
('',''),
(1,'Straw'),
(2,'Yellow'),
)
class Model1(models.Model):
user = models.ForeignKey(User,blank=True,on_delete=models.CASCADE)
Choice_A = models.IntegerField(choices=Choice1,default=0)
Views
def account(request):
review_list = Model1.objects.all
return render(request,"main/account.html", {'review_list':review_list})
HTML
<h6>Champagnes</h6>
{% for Model1 in review_list%}
<table class="table table-hover table-striped table-bordered ">
{% if Model1.user == user%}
<tr>
<th>Text</th><th>{{Model1.Choice_A }}</th>
</tr>
{%endif%}
</table>
{% endfor %}
You need to use the following in your template:
{{ Model1.get_Choice_A_display }}
It will render the string instead of the integer
You do this with the .get_fieldname_display(…) method [Django-doc], so here get_Choice_A_display:
<th>Text</th><th>{{Model1.get_Choice_A_display }}</th>
Note: normally the name of the fields in a Django model are written in snake_case, not PascalCase, so it should be: choice_a instead of Choice_A.
Related
I have a table inside form. It looks like below:
{% extends "base.html" %}
{% block title %}Title{% endblock title %}
{% block content %}
<form actions="" method="post">
{% csrf_token %}
<table>
<table border = "1" cellpadding = "10" cellspacing = "10" bordercolor = "green">
<tr>
<th>numbers</th>
<th>Extension</th>
<th>Vendor</th>
</tr>
{% for number in numbers %}
<tr>
<td>{{ number }}</td>
<td class = "select">Select Extension
<select name="extensions">
{% for obj in sipextensionsets %}
<option value={{obj.sip_extension}}>{{ obj.sip_extension }}</option>
{% endfor %}
</select>
</td>
<td>vendor</td>
</tr>
{% endfor %}
</table>
<input type="submit" value="save"/>
</form>
{% endblock content %}
My forms.py is below:
from django import forms
from .models import column
class didsForm(forms.ModelForm):
class Meta:
model = column
fields = ('extension')
My views.py is below
def saveintodb(request):
try:
instance = coloumn.objects.get(pk=1)
except:
instance = coloumn(pk=1)
instance.save()
if request.method == 'POST':
dids_form = didsForm(data=request.POST['extensions'], instance=instance)
if dids_form.is_valid():
dids_form.save()
messages.success(request, "Settings updated. Please apply settings.")
else:
messages.error(request, "Error: Invalid settings.")
else:
dids_form = didsForm(instance=instance)
return render(request, 'dids/index.html', {'dids_form': dids_form})
In the table, there is a drop down (select tag). I want to save the data into database when user selects something from dropdown and clicks on save button. I know I have mistaken somewhere in views.
You're doing a few things wrong here, unfortunately.
The main problem is that you're passing request.POST['extensions'] as the data argument to your form on POST; but that argument is expecting the whole POST, not a single field.
Linked to that is that you have not used the same name for the field in the model and the field in the form. Although you say in your comment that this is intentional, there doesn't seem to be a reason for it, and it's breaking things. Give them the same name.
Thirdly, you aren't letting Django populate the form, or show any errors when it's not valid. You shouldn't be explicitly passing sipextenionset (although you actually don't seem to be passing that at all, so I'm not sure where it's coming from), and you certainly shouldn't be explicitly iterating. You should let Django display the field:
<td>{{ number }}</td>
<td class="select"><label for="id_extension">Select Extension</label>
{{ form.extension }}
</td>
Finally, I can't at all understand what you are doing with that outer for loop through numbers; you will end up with several values for extension, which is not expected by your form, your model, or your view.
I got a view that receives a model and field the user passes via post (existing model and field inside the app of course) and makes a queryset filter on it, then i need to show in my template that result in a table (name fields must be the column headers) and their respective values.
This what i got so far trying to serialize the queryset result in order to make it easier to show in template:
Views.py:
from django.contrib.contenttypes.models import ContentType
class CommitteeReport(BaseView):
template_name = 'committee/committee_report.html'
def post(self, request, **kwargs):
myfield = request.POST['field'].lower()
my_model = request.POST['model'].lower()
queryset_obj = ContentType.objects.get(model = my_model).model_class().objects.filter(**{myfield:True})
return render(request, self.template_name,{
'requirements': queryset_obj,
})
And my template:
<div class="tab-pane active" id="tab_1">
<table class="datatable table table-striped table-hover" cellspacing="0">
<thead>
<tr>
{% for key in requirements %}
<th>{{ key.fields.name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for item in requirements %}
<tr>{{ item.fields.value }}</tr>
{% endfor %}
</tbody>
</table>
</div>
Thing is, i don't get result or if i change the tag inside the template, i get the objects dictionary for every row.
Any idea of how to achieve what i need ?, thanks in advance.
You can get the list of fields of model using my_instance._meta.local_fields. So you could try this in your view before return:
if queryset_obj.exists():
fields = queryset_obj.first()._meta.local_fields
else:
fields = []
return render(request, self.template_name,{
'requirements': queryset_obj,
'fields': fields,
})
And then using the context variable fields in your template:
<table class="datatable table table-striped table-hover" cellspacing="0">
<thead>
<tr>
{% for field in fields %}
<th>{{ field.name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for req in requirements %}
<tr>
{% for field in fields %}
<td>{{ req|lookup:field.name }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
where you define a custom lookup template filter to fetch the field value:
def lookup(model, attr):
if hasattr(model, attr):
return getattr(model, attr)
else:
return None
Note: I'm assuming that all requirements are the same class and have the same structure, so that requirements.0, the first object in the QuerySet, is used for making the headers of the table.
Note 2: I haven't tried this, you might move some of the work to the view and pass easier variables as context variables (e.g. the list of field names).
Note 3: I haven't added error handling, you should check if model is actually a Model instance for example.
My Directories app has a predefined variety of different models each of which needs to be selected and returned with its corresponding objects. As a result, since my models are plenty and the user needs to select each one separately I made a dynamic form that passes the model table name m_tb_name which is retrieved by my views.py and returns the appropriate model as shown here:
*views.py*
def dlist(request):
#get the model table name from the form
m_tb_name= request.POST['model_classes_field']
#retrieve the model using the table name
model_class = get_model('Directories', m_tb_name)
# return all model data
model_list = model_class.objects.all()
# how the data will be handled in list.html template
#get fields and their names
fields = get_model_fields(model_class)
field_names = model_class._meta.get_all_field_names()
print 'You searched for: %r' % m_tb_name
return render(request, 'Directories/list.html', {'m_tb_name':m_tb_name, 'model_class':model_class, 'model_list':model_list, 'fields':fields, 'field_names':field_names})
And since I got the model, its fields and its objects.all() initialized I try to populate a table with the model's data. However, in my template I have this:
*list.html*
<table>
<tr>
{% for f in fields %}
<th>{{ f.verbose_name }}</th>
{% endfor %}
</tr>
{% for f in fields %}
{% for mod in model_list %}
<tr>
<td> {{mod.f }}</td>
</tr>
{% endfor %}
{% endfor %}
</table>
And although I was expecting some data in my mod.f (specifically I was expecting the data for each particular field of the model) the output is empty, nothing is returned. Any ideas of why this is happening would be helpful.
The idea was to do something like the anwser in this question but with dynamic fields not hard coded ones.
Models don't have an f attribute, which is how your template variable is being parsed. If you want to do a dynamic lookup on mod with the value of f, you will need to write a simple template filter.
Currently, I am building a form using the default django template like this:
class old_form(forms.Form):
row_1 = forms.FloatField(label='Row 1')
row_2_col_1 = forms.FloatField(label='Row 2_1')
row_2_col_2 = forms.FloatField(label='Row 2_2')
html = str(old_form())
However, I would like to add multiple columns to my template, and still use django forms object to define parameters.
New temp. should something like (or it can loop through all the variables):
def getdjtemplate():
dj_template ="""
<table>
<tr>{{ table.row_1 }}</tr>
<tr>
<td>{{ table.row_2_col_1 }}</td>
<td>{{ table.row_2_col_2 }}</td>
</tr>
"""
return dj_template
djtemplate = getdjtemplate()
newtmpl = Template(djtemplate)
My question is how to 'combine' the new template and class old_form()?
Thanks for the help!
You can customize the form HTML using its fields, as shown in the documentation. You are doing this in an unusual way; normally you would have the template in a file instead of returning it from a function, but you can still do this:
from django.template import Context
def getdjtemplate():
dj_template = """
<table>
{% for field in form %}
<tr>{{ field }}</tr>
{% endfor %}
</table>
"""
return dj_template
form = old_form()
djtemplate = getdjtemplate()
newtmpl = Template(djtemplate)
c = Context({'form': form})
newtmpl.render(c)
I'd like to know how can I add .error class to input elements (to registration app) when the form validation fails.
If you want to place your error CSS class to form input widgets (not their containers), you can derive your form class from the following one:
class StyledErrorForm(forms.Form):
def is_valid(self):
result = super().is_valid()
# loop on *all* fields if key '__all__' found else only on errors:
for x in (self.fields if '__all__' in self.errors else self.errors):
attrs = self.fields[x].widget.attrs
attrs.update({'class': attrs.get('class', '') + ' is-invalid'})
return result
It's now easy -- new feature in Django 1.2
Just add an attribute on the form class & you're good to go. This feature is mentioned in the docs under a "new in 1.2" note, but you can find the magic at django.forms.forms.BoundField.css_classes Here's the API reference, and an example:
class MyForm(forms.Form):
required_css_class = "required"
error_css_class = "error"
This can be done completely through your template.
You build the form template for each form field that you want to test you can use the following example construct
<input type="text" class="reg-txt{% if form.fieldname.errors %} errors{% endif %}"/>
This lets you provide the interface you want without modifying the view & django form code.
Using a Custom Template...
Personally never had much luck using the built in Django error classing solutions, and besides, I like to use the built in 'striptags' template filter on the errors, to get rid of all the html list stuff which I cant figure out how to render nicely anyway.
I use the following custom template to class them as 'error_id'.
#register.filter(is_safe=True)
#stringfilter
def error_id(value):
if value=='':
return ''
else:
return r'<span class="error_id">'+value+'</span>'
Render the individual errors in your template using:
{{ form.my_field.errors|striptags|error_id}}
Or render the whole form using something like:
<table border="1" cellpadding="5px" align="center">
{% for field in form.visible_fields %}
<tr>
<td> {{ field.label_tag }}: </td>
<td> {{ field }} </td>
<td> {{ field.errors|striptags|error_id }} </td>
</tr>
{% endfor %}
</table>
(Better late than never)
You should be able to do this with Django Uni Form