Django, best way to print a field key - django

I want to print fields of a model differently than by first_name
I want to print something like "key: value" but it prints "first_name: Georges", I would prefer that it's looks like "First name: Georges"
Currently i'm using a file named form.html that I include in every form template:
{% load widget_tweaks %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text }}
</small>
{% endif %}
</div>
{% endfor %}
And a model that looks like this:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
What is the best way to print first_name as "First name"?:
Is it by setting verbose_name for every fields in the models.py?
Or by setting label in the forms.py for every fields in each form?
Or by not using a dynamic template and hardcode it in my form.html?

Like what Aleksei Maide said to change that you need to alter the Label, here is an example:
in your form class add a method:
def __init__(self, *args, **kwargs):
super(YourFormName, self).__init__(*args, **kwargs)
self.fields['first_name'].label = "First name"
this is how i'm displaying it in my template:
<label class="bmd-label-static">{{ field.label }}</label>
{{ field.name }}

Think by a moment that you have a Model Form with 30 fields, and as this form, you have other 30 more Model Forms, now, you have to set every time your field labels, is a very complicated task, don't you think?
i could suggest you that use the verbose name feature to each model field and build a simple template tag that can help you to get dinamicaly the verbose name of your fields i your templates
This template tag will try to get the model field's verbose name
# yourapp/templatetags/yourapp_extras.py
from django import template
register = template.Library()
#register.simple_tag
def field_name(model, field):
field_name = field
if model:
try:
field_name = model._meta.get_field(field).verbose_name.title()
except Exception as ex:
print ex
return field_name
And in your template you can display your field label as follow
# sometemplate.html
{% load widget_tweaks %}
{% load yourapp_extras %}
{% for field in form %}
<div class="form-group">
{% field_name model field.name %} <!-- here -->
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text }}
</small>
{% endif %}
</div>
{% endfor %}

Related

Setting css class to field in form depending of it's type

I want to manually render login and signup forms in Django.
Here is my code:
{% load widget_tweaks %}
{% for field in form.visible_fields %}
<div class="field">
<label class="label">{{ field.label_tag }}</label>
<div class="control">
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="nice-looking-field"%}
{% for error in field.errors %}
{{ error }}
{% endfor %}
{% else %}
{% render_field field %}
{% endif %}
{% else %}
{% render_field field %}
{% endif %}
{% if field.help_text %}
<p>{{ field.help_text }}</p>
{% endif %}
</div>
</div>
{% endfor %}
{% if form.non_field_errors %}
<div class="box">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
My question: is it possible to check in a loop what type the field has and, depending on the field, assign a specific CSS class?
For example:
Field_1 has type text, so we apply css-class-1 to it
Field_2 has a checkbox type, so we apply css-class-2 to it
you can use the django form that is inherited from modelform to define specific css class to the form fields.
for instance,
models.py file:
class Post(models.Model):
title=models.CharField(max_length=254)
text=models.TextField()
forms.py file
from . import models
class PostForm(forms.ModelForms):
class Meta():
model=models.Post
fields='__all__'
widgets={
'title':forms.TextInput(attrs={'class':'textinputclass'}), #--->> you can use this textinputclass as the css class in your css file to style the title field of your forms.
'text':forms.Textarea(attrs={'class':'content'})
}
now in your static>css>yourcss.css you can access the class that we defined above as normal css class.
.content{
font-size:15px;
}
That's all.

How can I show help_text attribute through for loop in my template?

forms.py
class UserRegistratiion(forms.Form):
email = forms.EmailField()
name = forms.CharField(help_text="80 Char Maximum")
views.py
def showFormData(request):
fm = UserRegistratiion(auto_id="my_%s")
return render(request, "blog/login.html", {"form":fm})
When i use this in my template it works fine and my help_text shows in span tag..
<form action="">
<div>
{{form.as_p}}
</div>
But, whwn i use for loop
{% for field in form.visible_fields %}
<div>
{{field.label_tag}}
{{field}}
</div>
{% endfor %}
help_text doesn't show how can i get this?
try this
{% for field in form.visible_fields %}
<div>
{{ field.label_tag }}
{{ field }}
{{ field.help_text }} <!-- new -->
</div>
{% endfor %}
or
{% for field in form.visible_fields %}
<div>
{{ field.label_tag }}
{{ field }}
{% if field.name =='name' %}
{{ field.help_text }} <!-- new -->
{% endif %}
</div>
{% endfor %}

How to create and submit multiple instances of a form on a single page?

I want 3 instance of a URL input form so I can submit up to 3 different URLs.
forms.py
class AdditemForm(forms.Form):
url = forms.URLField(
label='Add Item',
widget=forms.URLInput(
attrs={
"class": "form-control",
}))
view.py
def ItemDetail(request, pk):
listitem = comparelist.objects.get(id=pk)
if request.method == 'POST':
form = AdditemForm(request.POST)
if form.is_valid():
url = form.cleaned_data.get("url")
items.objects.create(
link=url,
name=product_name,
price=price,
store=store,
)
return HttpResponseRedirect(request.path_info)
else:
form = AdditemForm()
template = 'itemdetail.html'
context = {
"comparelist": listitem,
"form": form,
}
return render(request, template, context)
I'm using a form snippet I found in a tutorial:
{% load widget_tweaks %}
<form method="post" class="form">
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
So how do I get 3 of those forms on my page and be able to submit 3 different URLs?
I can only think of having to create 3 different form classes and paste the form snippet 3 times into the template. But that seems like a lot of unnecessary repetition.
Why "create 3 different form classes" ??? You can just create three instances of the same form.
paste the form snippet 3 times into the template
Ever heard about lists and loops ? You can put the three (or more) forms in a list and loop over it.
BUT that's actually not the best solution here - Django has Formsets for this use case.

Django selectdatewidget how to render manually?

I'm trying to render a selectdatewidget in django out manually so I can customise with bootstrap. However I'm not clear on how I render out the indvidual inputs with the selectdatewidget?
class ProfileForm(forms.Form):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
eighteen_years_from_now = (datetime.datetime.now().year - 18)
date_of_birth = FieldBuilder(User, 'date_of_birth', widget=SelectDateWidget(
years=range(eighteen_years_from_now, 1919, -1)))
template to render an individual field:
<div class="form-group">
<label for="{{ field.id_for_label }}" class="sr-only">
{{ field.label }}
</label>
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" placeholder=field.label %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
The short answer is that you can't get the control needed, without overriding the inbuilt django template.
Thankfully Django 1.11 changed the widget system to use templates rather than python code making this easier to override.
From reviewing the templates in django/forms/templates/django/forms/widgets we can see that the select date widget loads the multiwidget template which for each subwidget loads the widget template:
{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}
For select date widget this means the output is the 3 select tags (month, day, year) next to each other. This can't be eg made inline with bootstrap as each <select> needs to be wrapped in a div with the appropriate css class.
Templates can be overriden by following the django docs here:
https://docs.djangoproject.com/en/1.11/ref/forms/renderers/#overriding-built-in-widget-templates

How to insert extra content in form?

I have form:
class ItemForm(forms.ModelForm):
id = forms.ModelChoiceField(queryset=Item.objects.all(), widget=forms.HiddenInput())
temp = forms.BooleanField(widget=forms.HiddenInput(), required=False)
date = forms.SplitDateTimeField(widget=forms.SplitDateTimeWidget())
... etc
and in template i have:
{% for field in itemForm %}
{% if field.is_hidden %}
{{ field }}
{% else %}
<div class="fieldWrapper">
{% if field.errors %}<div class="errorbox">{% endif %}
<p>{{ field.label_tag }}</p>
<p>{{ field }}</p>
<p></p>
{% if field.errors %}<p>{{ field.errors }}</p></div>{% endif %}
</div>
{% endif %}
{% endfor %}
it is a universal template for different forms. And now in one form:
class DifferentForm(forms.ModelForm):
id = forms.ModelChoiceField(queryset=DifferentItem.objects.all(), widget=forms.HiddenInput())
option = forms.ModelChoiceField(queryset=Option.objects.all(), widget=forms.HiddenInput())
(????)
temp = forms.BooleanField(widget=forms.HiddenInput(), required=False)
date = forms.SplitDateTimeField(widget=forms.SplitDateTimeWidget())
... etc
i want put an additional link in such a way as to show in this way:
<select ...>
<option>...</option>
</select>
(my additional link, button, text, whatever)
<input ...
How to do it?
The way I usually do this is in the template:
{% for field in itemForm %}
{% if field.name == "option" %}
Custom stuff I want to go before this field
{% endif %}
<!-- Regular field stuff goes here -->
{% if field.is_hidden %}
{{ field }}
{% else %}
<div class="fieldWrapper">
...
</div>
{% endif %}
<!-- End Regular Field Stuff -->
{% if field.name == "option" %}
Custom stuff I want to go after the field
{% endif %}
{% if field.name == "another_field_name"%}
Custom stuff I want to go after the field
{% endif %}
{% endfor %}