How to keep 2 fields using django forms - django

As django forms run a loop for the fields
{% for field in form %}
<div class="col-6">
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
I actually want to have 2 fields, I found a cheap solution to this issue using Bootstrap4
I created the columns by using col-6 by which I get 2 fields in the row. But what if I want to make custom designs of forms in django ?

Personally i am using this method to show only fields i want and then have if statements for the way each field should be shown
{% for i in form %}
{% if i.name in 'title,address,city' (Fields you want to show) %}
{% for error in i.errors %}
<div>
<li><strong>{{ error|escape }}</strong></li>
</div>
{% endfor %}
<p>
<label>{{i.label}}:</label>
<input type="text" name="{{i.name}}" required id="id_{{i.name}}">
</p>
{% endif %}
{% endfor %}
And like that you can style it however you want and show only those you want to show

Related

What is form.visible_fields in Django and how do I index into it?

Sometimes I have the need to render a particular Django form field in a particular way. I would like to be able to access this field and only this field in order to customize its rendering in my template.
I know, for example, that I can do something like this:
<!--Access the form field at index 2-->
{% for field in form.visible_fields %}
{% if forloop.counter == 2 %}
<!--Render my form field the way that I want to-->
{% endif %}
{% endfor %}
Intuitively, I would expect to be able to do something like {{ form.visible_fields[2] }} or perhaps {{ form.visible_fields['field_name'] }}.
Unfortunately, my various attempts at the above have all failed and so I'm left wondering if this is possible. Any advice?
According to Django documentation you should be able to something like this:
{# Include the hidden fields #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# Include the visible fields #}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}

Django: For Loop to Iterate Form Fields

I don't want to use django's built in form generation, seeking to specify each field in my template in order to customize the html output.
How do I iterate over a series of form fields?
If my form looks like this:
class MyForm(forms.Form):
main_image = forms.ImageField()
second_image = forms.ImageField()
third_image = forms.ImageField()
fourth_image = forms.ImageField()
...
Is there way to write a {% for %} loop so that I can iterate through:
{{ form.main_image }}
{{ form.second_image }}
{{ form.third_image }}
{{ form.fourth_image }}
I tried the following which seemed logical, but did not work:
{% for field in form %}
{{ form.field }}
{% endfor %}
Well this would clearly not work:
{% for field in form %}
{{ form.field }}
{% endfor %}
but this will:
{% for field in form %}
{{ field }}
{% endfor %}
The best way is to use two loops, one for hidden fields and one for visible fields :
visibles:
{% for field in form.visible_fields %}
{{ field.label }}
{{ field }}
{% endfor %}
hiddens:
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
in this way you will have better control over UI elements.
This one should work :
{% for field in form %}
{{ field }}
{% endfor %}
Once you loop through field in form , you can't access form.field
For any frontend developers looking to customize a Django form you can use a package called django-widget-tweaks to render fields individually. Example code below:
{# Your template with the form #}
{% extends "base.html" %}
{% load widget_tweaks %}
<form action="" method="POST">
{% csrf_token %}
{% for field in form %}
<label for="{{ field.id_for_label }}">
{{ field.label }}{% if field.field.required %}*{% endif %}
</label>
{% render_field field %}
{% endfor %}
<button type="button">
Submit Form
</button>
</form>
Note: You'll want to make this look nicer of course, and you may want to loop through your form errors if there are any.
They have some very useful examples on their PyPi page as well.

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.

Trying to access ModelForm field modelChoice choices in Django template

I'm generating ModelForms and want some granular control over how they are output in my template. Specifically, I need to add some markup to the end of each radio button in each of my select lists.
Code:
# order-form.html
{% load catname %}
<form id = "order-form">
{% for form in forms %}
<div id="gun-{{ forloop.counter }}">
{% for field in form.fields %}
<div id="{{ field }}-item" class="item">
<h3>{{ field|catname }}</h3>
{% for choice in form.field.choices %} {# <-- Help me out here #}
{{ choice.id }}
{{ choice.title }}
{% endfor %}
</div>
{% endfor %}
{% endfor %}
<button type="submit" id="standard-gun-form-submit">Continue to next step</button>
</form>
# views.py
def get_form(request):
if request.method == 'POST':
if request.POST['gun_type'] == 'standard':
forms = [StandardGunForm(prefix=p) for p in range(0,2)]
return render_to_response('main/order-form.html', {'forms' : forms,}, RequestContext(request))
# forms.py
class StandardGunForm(ModelForm):
def __init__(self, *args, **kwargs):
super(StandardGunForm, self).__init__(*args, **kwargs)
for field in self.fields:
if isinstance(self.fields[field], ModelChoiceField):
self.fields[field].empty_label = None
class Meta:
model = BaseGun
widgets = {
'FrameTuning' : RadioSelect(),
'FrameConnection' : RadioSelect(),
}
exclude = ('price')
Endgame: markup that looks like this
<form id="foo">
<div class="category">
<div class="item">
<input type="radio" name="srsbzns" value="1">Option 1</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
<div class="item">
<input type="radio" name="srsbzns" value="2">Option 2</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
<div class="item">
<input type="radio" name="srsbzns" value="3">Option 3</input>
<img src="http://placekitten.com/150/150">
<p>Other foo here</p>
</div>
</div>
</form>
From the shell, this returns what I want
>>> forms = [StandardGunForm(prefix=p) for p in range(0,2)]\
>>> forms[0].fields['frame_tuning'].choices.queryset
I'm surprised this is proving so challenging!
Bonus: I have DEBUG = True and Django Debug toolbar enabled. Is it possible to dump the variables to the browser, so I can see what this stuff looks like as I drill down?
Thanks!
I had to do something similar and started down this path as well. I wanted to create table rows from a ModelChoiceField where each column had a different field of the model instance (and then I'd allow filtering the table rows via JavaScript).
I couldn't find it in the Django docs, but a quick perusal of the Django source showed the way. You can get to the queryset to access the model instances like so:
<form action="{% url 'some_view' %}" method="post">
{% csrf_token %}
{% if form.non_field_errors %}
{{ form.non_field_errors }}
{% endif %}
{% for field in form %}
{{ field.label }}
{% if field.field.choices %}
{% for model_instance in field.field.choices.queryset %}
{{ model_instance.id }}
{% endfor %}
{% else %}
{{ field }}
{% endif %}
{% if field.errors %}
{{ field.errors|striptags }}
{% endif %}
{% endfor %}
<button type="submit">Submit</button>
</form>
However, at this point we've disassembled the shiny widget (in my case a CheckboxSelectMultiple) and must re-assemble the HTML form input using template code. I found no direct way to simultaneously iterate over the ModelChoiceField to access the model instance fields and get the HTML form tags for the choices.
Maybe there's a way, but I abandoned my attempt and built my own HTML form, handling all the POST data in a view. It ended up much easier that way. ModelForms are really nice and convenient, but using them for something they weren't built for can end up being more difficult.
I figured I'd post this in case anyone is trying to do it for some other reason. Hope it helps.
Very late, but I'm reading now and this is what it worked for me
{% for field in form %}
{% for x, y in field.field.choices %}
{{x}}
{{y}}
{% endfor %}
{% endfor %}
Where "x" is the id or code, and "y" is the readable value or title.
You can access the underlying model instance for each choice:
{% for choice, label in form.field_name.field.choices %}
{{ choice.value }}
{{ choice.instance }}
{{ choice.instance.instance_attribute }}
{{ label }}
{% endfor %}
{% for choice in form.field.choices %} {# <-- Help me out here #}
{{ choice.id }}
{{ choice.title }}
{% endfor %}
Look what you're doing here, you're literally trying to access a field called "field" every time in this loop, which presumably does not exist.
You need to take the field object you're iterating through, and access the choices attribute on that.
{% for field in form.fields %}
{% for choice in field.choices %}

Django form template

If there were field.errors in django, how to to add css class to {{ field }}, example at bottom
{% for field in form %}
{{ field }}
{% if field.errors %}{{ field.errors }}{% endif %}
{% endfor %}
Aiming for {{ field }} input type that would have "class=error" when ever there was an error
<input class="error">
You can add the class to a wrapper around the field. Django also does this by itself when defining classes in forms.py or views.py
{% for field in form %}
<p {% if field.errors %}class="error"{% endif %}
{{ field }}
</p>
{% if field.errors %}{{ field.errors }}{% endif %}
{% endfor %}
Unfortunately this seems to be the only way.
Even when Django adds the classes itselt, it prefers to add them to a wrapper of some sort.
http://docs.djangoproject.com/en/dev/ref/forms/api/#more-granular-output
Scroll down to read about the new thing in 1.2 about adding css classes.
Using this, you can just use form.as_p (or whatever suits you) as the elements will have all the classes as you define them.
Hope this was a little bit of help.
You can use widget_tweaks api to do that.
Instead of rendering a form with
{{ form.field }}
You should use:
{% load widget_tweaks %}
{% render_field form.field class="error" %}