How to insert extra content in form? - django

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 %}

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 %}

Django, best way to print a field key

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 %}

Django form.MultipleChoiceField . Customize checkboxes in template

I have this form:
class PasswordForm(forms.Form):
CHOICES=[('uppercase','Uppercase'),
('lowercase','Lowercase'),
('numbers','Numbers'),]
password_length = forms.ChoiceField(choices=[(x, x) for x in range(1, 32)],)
options = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple, choices=CHOICES,)
How can I customize in template my checkbox fields?
I know how I can do it with other fields, like forms.Charfield() or my password_length, just
<form action="" method="post">
{{form.some_field}}
</form>
but it doent works with my MultipleChoiceField, I tried many things like
{{form.uppercase}}, {{form.options.choices.uppercase}} and tried {% for %} loop.
it just return nothing, and I dont see it in html via browser inspector.
<!-- With for-cycle: -->
{% for field in form %}
{% for choice_id, choice_label in field.field.choices %}
{{choice_id}}
{{choice_label}}
{% endfor %}
{% endfor %}
<!-- And my end version, where I edited only certain field. -->
{% for field in form %}
{% if field.name == "your-field-name-here"%}
<p><strong>{{field.name}}: </strong></p>
{% for choice_id, choice_label in field.field.choices %}
<input type="checkbox" name="category" value="{{choice_id}}" style="display:inline;">{{choice_label}}
{% endfor %}
{% else %}
<p>{{ field.errors }}<label style="display:table-cell;">{{field.name}}: </label>{{ field }}</p>
{% endif %}
{% endfor %}
<!-- If you want to edit all fields with options: {% if field.choices %} -->
You should write these options as fields of the form:
class PasswordForm(forms.Form):
uppercase = forms.CharField(widget=forms.CheckboxInput())
lowercase = forms.CharField(widget=forms.CheckboxInput())
numbers = forms.CharField(widget=forms.CheckboxInput())
password_length = forms.ChoiceField(choices=[(x, x) for x in range(1, 32)],)
and then render the form to template, and in template:
{{ form.uppercase }}
will show
<input name="uppercase" type="checkbox">

ListField is showing <ul> instead of <input> in edit/create post

I am using Flask, mongoengine for a project and I am trying to get basic stuff working from http://docs.mongodb.org/manual/tutorial/write-a-tumblelog-application-with-flask-mongoengine/
After implementing everything from above link I added a new field for "tags" in Post and when I try to create a post, my tags doesn't show a input box.
Any help is appreciated.
My code and screenshot below
class Post(db.DynamicDocument):
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
title = db.StringField(max_length=255, required=True)
slug = db.StringField(max_length=255, required=True)
comments = db.ListField(db.EmbeddedDocumentField('Comment'))
tags = db.ListField(db.StringField(max_length=30)) # New field I added
template form
{% macro render(form) -%}
<fieldset>
{% for field in form %}
{% if field.type in ['CSRFTokenField', 'HiddenField'] %}
{{ field() }}
{% else %}
<div class="clearfix {% if field.errors %}error{% endif %}">
{{ field.label }}
<div class="input">
{% if field.name == "body" %}
{{ field(rows=10, cols=40) }}
{% else %}
{{ field() }}
{% endif %}
{% if field.errors or field.help_text %}
<span class="help-inline">
{% if field.errors %}
{{ field.errors|join(' ') }}
{% else %}
{{ field.help_text }}
{% endif %}
</span>
{% endif %}
</div>
</div>
{% endif %}
{% endfor %}
</fieldset>
{% endmacro %}
rendering form code
{% extends "admin/base.html" %}
{% import "_forms.html" as forms %}
{% block content %}
<h2>
{% if create %}
Add new Post
{% else %}
Edit Post
{% endif %}
</h2>
<form action="?{{ request.query_string }}" method="post">
{{ forms.render(form) }}
<div class="actions">
<input type="submit" class="btn primary" value="save">
Cancel
</div>
</form>
{% endblock %}
From what I can gather, your problem is you're telling WTF to render the tags field, but WTForms doesn't know how to handle that information.
From looking at the Flask-MongoEngine documentation, it seems the ListField is just a FieldList as WTForms refers to it.
Currently you're not actually defining the form independently in WTForms, you're just using the magic included in Flask-MongoEngine, so my first attempt would be to add some more logic to your macro, add a {% elif field.type == 'ListField' %} and try and discover what's contained in there to iterate through to produce your form. From having a quick look at the source-code, something like the following might work.
{% elif field.type == 'ListField %}
{# render_the_group_label #}
{% for subfield in field.entries %}
{% if subfield.type == 'StringField' %}
{# render_the_subfield #}
{% endif %}
{% endfor %}
...
That code will need to be worked on, but hopefully it'll point you in the right direction. Otherwise, I'd actually define the form seperately in WTForms to give you a bit more control on the code-side. Luckily they provide a csv tag example which should help you if you need to go that route. I wrote a guide that takes a different route using #property decorators to achieve a similar effect, which again, might at least point you towards the finish line.