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.
Related
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/
I was looking for a solution but nowhere to find the right answer. Maybe the answer I am looking for does not exist, so I decided to ask a question here just in case.
I try to show a date without a day. But the problem is that the date is displayed as one of form fields that I create from the model in the database. I explained this because I am not trying to show only the date separately in the temple but the whole form. I'm showing the form in the template using {{form.as_p}}. My date always shows dd.mm.YYYY, but I want to display a date without a day. The form is used to update existing data in the database. Is there a solution, to define certain parameters in the form class I created in the forms.py file or I must do something else?
Suppose this is your forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=30)
email = forms.EmailField(max_length=254)
message = forms.CharField(
max_length=2000,
widget=forms.Textarea(),
help_text='Write here your message!'
)
source = forms.CharField( # A hidden input for internal use
max_length=50, # tell from which page the user sent the message
widget=forms.HiddenInput()
)
You can render it manually like this:
<form method="post" novalidate>
{% csrf_token %}
{% if form.non_field_errors %}
<ul>
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{% for hidden_field in form.hidden_fields %}
{% if hidden_field.errors %}
<ul>
{% for error in hidden_field.errors %}
<li>(Hidden field {{ hidden_field.name }}) {{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ hidden_field }}
{% endfor %}
<table border="1">
{% for field in form.visible_fields %}
<tr>
<th>{{ field.label_tag }}</th>
<td>
{% if field.errors %}
<ul>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ field }}
{% if field.help_text %}
<br />{{ field.help_text }}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<button type="submit">Submit</button>
</form>
Now you can apply date filter to your fields:
{{ value|date:"D d M Y" }}
You can read more about date filter as pre your need i.e., to get only date or time : https://docs.djangoproject.com/en/2.2/ref/templates/builtins/#date
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/
I want to print value by id in database,And don't know which keywords to find in Google.
in my views.py, I send transen = TransEn.objects.all() to template
and this will print all datas from database:
{% for words in transen %}
{{words.words|safe }}
{% endfor %}
But I want to print by the value of the id Like:
(Because they are words in English for translating website)
I don't know how to write this in template, please guide me, Thank you very much.
<div><span> TransEn.objects.filter(id='2') </span></div>
<div> TransEn.objects.filter(id='3') </div>
UPDATE:
I have found a method:
I can use if tag, but are there another ideas??
<div>
{% for words in transen %}
{% if words.id == 2 %}
{{ words.words|safe }}
{% endif %}
{% endfor %}
</div>
<div>
{% for words in transen %}
{% if words.id == 3 %}
{{ words.words|safe }}
{% endif %}
{% endfor %}
</div>
If you want to access each item in the QuerySet individually, by index, you should cast it to a list first. You should change your views.py to:
transen = list(TransEn.objects.all())
And then in your template you can access them by index like so:
<div><span> {{ transen.1.words }} </span></div>
<div> {{ transen.2.words }} </div>
A warning from the Django docuemtnation about casting a QuerySet to a list:
Be warned, though, that this could have a large memory overhead, because Django will load each element of the list into memory. In contrast, iterating over a QuerySet will take advantage of your database to load data and instantiate objects only as you need them.
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 %}