How can I show a specific django field in html? - python

So I want to do what the title says and I don't know how since I'm new at this.
<p>{{ form.description }}</p>
That's the way I show information from different models in a listing using
{% for form in forms %}
But I want to show the description of an specific object.
Thanks in advance.

<form method="post" novalidate>{% csrf_token %}
{{ form.non_field_errors }}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field.errors }}
{{ hidden_field }}
{% endfor %}
<table border="1">
{% for field in form.visible_fields %}
<tr>
<th>{{ field.label_tag }}</th>
<td>
{{ field.errors }}
{{ field }}
{{ field.help_text }}
</td>
</tr>
{% endfor %}
Look this article: [link][1]https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html

Usually django templates will be filled with the data rendered from the django views as dictionary and these will be callable in templates using django template tags "{{tag_name}}"
Here you will be rendering all the forms as a list inside the dictionary so you can show each form by looping it.
{% for form in forms %}
{{form.description}}
{% endfor %}
Like this, you can show each form's data. Instead of this if you only want to show a specific form's data then the proper way is to render the view with the specific form's data and show data in template using the template tag {{form.description}}
Check the django documentation : https://docs.djangoproject.com/en/2.1/topics/templates/

Related

How to add an attribute to the form tag itself and not just a field in Django?

I am having trouble stopping bots filling in spam while letting through legit users. I have a honeypot field with autocomplete="off" attribute but it doesn't seem to be working. From what i've read, the best cross browser solution is to add autocomplete="false" to the main form tag itself, e.g. <form autocomplete="false">...</form>. What is the best way to do this in Django?
Just do that in your template where the form is added.
In a template you'd typically do something like;
<form autocomplete="false">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.label }}
{{ field }}
{{ field.help_text }}
{% endfor %}
So just add whatever you want to the form tag.
You should probably also have a look at including recaptcha if you've got spam problems.
And remember that v3 doesn't require any selecting street lights etc
https://pypi.org/project/django-recaptcha/

The If equal not working in Django Template

I am able to fetch these two values in the Django HTML template :
{{ user.get_username }}
{{ post.user }}
But when I use them further to compare their values in an IF condition, it doesn't work.
{%for post in post%}
<h1>{{post.title}}</h1>
<h2>{{post.content}}</h2>
<p>{{post.date}}</p>
{%if user.is_authenticated%}
<h3> {{ user.get_username }}</h3>
<h3> {{post.user}} </h3>
{%ifequal user.get_username post.user%}
<form action="{%url 'post_delete' post.id %}" method="POST">
{%csrf_token%}
<button type="submit">Delete</button>
</form>
{%endifequal%}
{%endif%}
{%endfor%}
I've also tried {% if user.get_username == post.user %} as well, but it didn't help either.
Please help. I need the delete button only against the posts of logged in user.
{{ user.get_username }} and {{ post.user }} are different objects.
If you want to compare the "string" representation of both (thats what you see in the rendered template), you have to convert {{ post.user }} to a string. (I'd convert them both, since I don't know if you user_name is also a string (it should be, though).
Use:
{% if user.get_username|stringformat:'s' == post.user|stringformat:'s' %}
Check documentation here:
Django Template Tag: Stringformat
Python Conversion Types (I.e. 's')
Did you tried solution provided here:
compare two variables in jinja2 template
{% if user.get_username|string() == post.user|string() %}
{% if user == post.user %} worked for me.
Looks like 'user.get_username' was not working. Just 'user' worked. I wonder why though.
{% if notification.status|stringformat:'s' == 'Approved' %}
<td><div class="badge badge-success">{{ notification.status }}</div></td>
{% else %}
<td>{{ notification.status }}</td>
`{% endif %}'

Is there a way to hide the csrf label while looping through form using Flask and Flask-WTForms?

I have very simple contact form and I would like to hide the label somehow so that it doesn't show Csrf Token. I am using Flask and Flask-WTForms and am rendering the form like this:
{% for field in form %}
{{ field.label }}
{{ field }}
{% endfor %}
So basically this shows my inputs correctly and the csrf oen is hidden but the label isn't hidden? Should I get over it and implicitly say form.field_name instead of looping through the form or is there a way to handle this "corner case".
I was thinking about doing a logical check in either the for loop declaration or the label declaration but so far I haven't found anything in the documentation that has worked.
Thanks
EDIT: I have "fixed" the problem by doing this but it feels kinda dirty and hacky which I don't like I am still open to a better solution:
{% if not loop.first %}
{{ field.label }}
{% endif %}
If you want a more general solution that works for all hidden fields instead of just the CSRF token:
{{ form.hidden_tag() }}
{% for field in form if field.widget.input_type != 'hidden' %}
{{ field.label }}
{{ field }}
{% endfor %}
form.hidden_tag() is supplied by Flask-WTF.
Just to add to JD's excellent answer...
For those stumbling across this question: You can avoid losing the (csrf) hidden field (and thus protection) by adding the condition "if field.widget.input_type!='hidden' " specifically to the label instead of to the form iterator.
i.e.:
not
{{ form.hidden_tag() }}
{% for field in form if field.widget.input_type != 'hidden' %}
{{ field.label }}
{{ field }}
{% endfor %}
but
{{ form.hidden_tag() }}
{% for field in form %}
{% if field.widget.input_type != 'hidden' %} {{ field.label }} {% endif %}
{{ field }}
{% endfor %}
I think this should work too:
{% for field in form if field.id != 'csrf_token' %}
{{ field.label }}
{{ field }}
{% endfor %}
I have found the way to do it like this:
{% if field.id != 'csrf_token' %}
I believe this to be less hacky. I found this from modifying the example here in the docs.
I made a macro recently to submit forms through ajax in order to not reload the webpage and send it to the api directly.
{% macro render_fields3(form, form_name, method) %}
<form class="ajax" name={{ form_name }} method={{ method }}>
{{ form.hidden_tag() }}
{% for field in form if field.widget.input_type != 'hidden' %}
<dt>{{ field.label }}
<dd>{{field(id=field.name + method)|safe}}
{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</dd>
{% endfor %}
</form>
{% endmacro %}

Django admin display multiple fields on the same line

I have created a model, it will automatically display all the fields from the model and display it on the admin page.
Now, I have a problem, I would like to have two fields on the same line, to do this I have to specify the fieldsets at ModelAdmin:
fieldsets = (
(None, {
'fields': (('firstname', 'lastname'),)
}),
)
Do I have to specify all the fields? Because there are many fields in the database I need to specify.
Wrap those fields on their own tuple.
class TestAdmin(admin.ModelAdmin):
fields = (
'field1',
('field2', 'field3'),
'field4'
)
In the above example, fields field2 and field3 are shown on one line.
I'm afraid there's not an easy way to do it.
One option is to override the change_form.html template for that ModelAdmin and style the form as you like.
Another alternative is to do custom ModelForm and define a field with a widget that renders two input fields, in the form's .save() method, set the widget resulting value (a tuple) to both fields.
There is an article may be useful
http://amk1.wordpress.com/2010/09/23/a-2-column-django-admin-form/
Article is quote below:
Django is great. The bundled admin interface makes it better. But as the number of items on the form gets bigger, the amount of wasted space increases because the layout is single column. Coupled with left alignment on wide-screen monitors, my users usually end their day with a condition we call “eyeballs misalignment”.
So I improvised and changed the form (and StackedInline) to a 2-up layout. No more “eyeballs misalignment”.
The corresponding template for Django 1.2.1 (/contrib/admin/templates/admin/includes/fieldset.html) looks like this, modified lines highlighted:
<fieldset class="module aligned {{ fieldset.classes }}">
{% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
{% if fieldset.description %}
<div class="description">{{ fieldset.description|safe }}</div>
{% endif %}
<table border=0 width=100%>
{% for line in fieldset %}
{% cycle '<tr>' '' %}
<td width=50%>
<div style="border-bottom:0" class="form-row{% if line.errors %} errors{% endif %}{% for field in line %} {{ field.field.name }}{% endfor %}">
{{ line.errors }}
{% for field in line %}
<div{% if not line.fields|length_is:"1" %} class="field-box"{% endif %}>
{% if field.is_checkbox %}
{{ field.field }}{{ field.label_tag }}
{% else %}
{{ field.label_tag }}
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
{% else %}
{{ field.field }}
{% endif %}
{% endif %}
{% if field.field.field.help_text %}
<p class="help">{{ field.field.field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
</div>
</td>
{% cycle '' '</tr>' %}
{% endfor %}
</table>
</fieldset>
this has worked for me
fieldsets=(
("My Group",{"fields": (tuple(['field1','field1']),),}),
)
It's stupid, but yes, if you're going to use the fieldsets tuple-within-a-tuple method, you have to then specify all the fields that should show on your form.
Agreed, that its annoying, but its tuple of tuples from list of fields.
you can use list comprehension and change list to tuple.
Here is an example for skipping some fields, that you want to give some special attention WHILE including rest normal way.
skipped=[]
alist = [field.name for field in <model_name>._meta.fields if field.name not in skipped]
fieldsets = tuple(alist)
*** play with skipped ***
with small tweaking this should work.

Django: How to check if field widget is checkbox in the template?

I've created a custom template for rendering form fields:
<tr class="{{field.field.widget.attrs.class}}">
<th class="label">
<label for="{{field.auto_id}}">
{{field.label}}
{% if not field.field.required %}<span class="optional">(optional)</span>{% endif %}
</label>
</th>
<td class="field">
{{field}}
{% if field.errors %}<label class="error" for="{{field.auto_id}}">{{field.errors.0}}</label>{% endif %}
{% if field.help_text %}<small class="help-text">{{field.help_text}}</small>{% endif %}
</td>
</tr>
But I want to check if the widget is a checkbox, and if so, render it differently. How can I do that in the template?
Use a custom template filter!
In yourapp/templatetags/my_custom_tags.py:
from django import template
from django.forms import CheckboxInput
register = template.Library()
#register.filter(name='is_checkbox')
def is_checkbox(field):
return field.field.widget.__class__.__name__ == CheckboxInput().__class__.__name__
In your template:
{% load my_custom_tags %}
{% if field|is_checkbox %}
do something
{% endif %}
Side note on implementation: when I don't instantiate a CheckboxInput, the class name is MediaDefiningClass.
>>> form django.forms import CheckboxInput
KeyboardInterrupt
>>> CheckboxInput.__class__.__name__
'MediaDefiningClass'
{{ field.field.widget.input_type }} will get you this info for a lot of widgets, but not all. I'm not sure if it'll work for the default checkbox widget or not. Worth a shot.
It is kind of late to answer, but I implemented something similar to what is done in Django's admin.
First, I added a new attribute is_checkbox to the Field class:
# forms.py
from django import forms
from django.forms.fields import Field
setattr(Field, 'is_checkbox', lambda self: isinstance(self.widget, forms.CheckboxInput ))
Then, I can easily detect a CheckboxInput widget in the template. Here is an example to render checkboxes to the left and other widgets to the right:
{% if field.field.is_checkbox %}
{{ field }} {{ field.label_tag }}
{% else %}
{{ field.label }} {{ field }}
{% endif %}

Categories

Resources