How to display date from database in Django form without day - python

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

Related

Display error if there is error in fields

Im trying to raise error for empty fields or fields which are not validating in form
so Im doing this method below but I know this is not the best way...
views.py :
'KnowledgeForm': form,
'errors': str(form.errors),
but then in Django-template I have to use if for each field and im adding custom name for each field , i dont know why i cant use Verbose_name...
Template :
{% if errors %}
<div class="alert alert-danger">
<p>
{% if KnowledgeForm.errors.KnowledgeTitle %}
عنوان دانش: {{ KnowledgeForm.errors.KnowledgeTitle }}
{% endif %}
{% if KnowledgeForm.errors.KnowledgeTextSummary %}
Summary: {{ KnowledgeForm.errors.KnowledgeTextSummary }}
{% endif %}
{% if KnowledgeForm.errors.KnowledgeFromDate %}
from Date: {{ KnowledgeForm.errors.KnowledgeFromDate }}
{% endif %}
{% if KnowledgeForm.errors.KnowledgetoDate %}
To date : {{ KnowledgeForm.errors.KnowledgetoDate }}
{% endif %}
{% if KnowledgeForm.errors.KnowledgeProcess %}
Chart: {{ KnowledgeForm.errors.KnowledgeProcess }}
{% endif %}
{% endif %}
</p>
</div>
{% endif %}
Second method :
{% if KnowledgeForm.errors %}
<ul class="alert alert-danger">
{% for key,value in KnowledgeForm.errors.items %}
<li>{{ key|escape }} : {{ value|escape }}</li>
{% endfor %}
</ul>
{% endif %}
in this method i get the name based on whats used in models.py how can i change it?
The most clear and concise way is to use a forloop
Try replacing your entire if block in your HTML with the below code
{% for field in KnowledgeForm %}
{% if field.errors %}
<div class="alert alert-danger">
{{ field.label_tag }} {{ field.errors }}
</div>
{% endf %}
{% endfor %}
I don't think you need 'errors': str(form.errors),
It is because you convert errors to str and you don't need to separate this.
In your template:
# if you want to use verbose_name just use label_tag.
# label_tag is equal to your verbose name.
{% for field in KnowledgeForm %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
So you have the error top of input

How To Display One form error in Django

I have this in my template and i want only to display username error not all form errors
{% for field in form %}
{% for error in field.errors %}
<div class="row">
<div class="small-12 columns val-error-msg error margin-below">
{{ error }}
</div>
</div>
{% endfor %}
{% endfor %}
You could specify a field error with form.field_name.errors
like:
{% if form.username.errors %}
{{form.username.errors}}
# or
# {{form.username.errors.as_text}}
# this will remove the `<ul></ul>` tag that django generates by default
{% endif %}
Ever field has .errors attached to it as well. But note that each field can contain multiple errors (for example a password can be too short, and contain illegal symbols).
You can access these errors through {{ form.field.errors }}, but you already obtain such elements. In case you want to filter in the template to only show the errors of - for example - the username field, you can do so with an {% if ... %} statement:
{% for field in form %}
{% if field.name == "username" %}
{% for error in field.errors %}
<div class="row">
<div class="small-12 columns val-error-msg error margin-below">
{{ error }}
</div>
</div>
{% endfor %}
{% endif %}
{% endfor %}

Form data is not bound in dynamically added inline formset in Django

I got a question regarding the validation of a dynamically added inline formset in Django. It seems like I am missing something in my implementation.
Here is my case:
My project is a team management platform. A team is called Crew and can have several time Schedules. Each Schedule can have several Shifts. Please take a look at my code. At the moment I am able to create a schedule with several, dynamically added forms of the formset for the Shifts, if all fields are valid.
If not, the error for the Shift forms is not displayed and it is filled with the initial data again. It looks like the data of the shift forms is not bound after sending the POST request (because form.is_bound() is false). Moreover the data of Shift forms is not populated again after the POST request.
What do you think is the cause of this behaviour? Do I have to overwrite the is_valid function? I dont know, because it looks like the function works fine - the data is just not bound correctly to the new forms.
Views.py
def schedule_add(request, crew_id):
if request.method == "GET":
form = ScheduleForm()
ShiftFormSet = formset_factory(ShiftForm)
return render(request, 'schedule_add2.html', {'form': form, 'formset': ShiftFormSet, 'title':"Zeitplan hinzufügen"})
elif request.method == "POST":
form = ScheduleForm(request.POST)
numberOfShifts = int(request.POST['form-TOTAL_FORMS'])
ShiftFormSet = formset_factory(ShiftForm, extra=numberOfShifts)
shift_formset = ShiftFormSet(request.POST, prefix='form')
print(request.POST)
if form.is_valid() and shift_formset.is_valid():
schedule = Schedule()
schedule.name = form.cleaned_data.get('name')
schedule.crew = Crew.objects.get(pk=crew_id)
schedule.location = form.cleaned_data.get('location')
schedule.subperiod = form.cleaned_data.get('sub_period')
schedule.save()
for shift_form in shift_formset:
if shift_form.is_valid():
shift = Shift()
shift.min_user_count = shift_form.cleaned_data.get('min_user_count')
shift.max_user_count = shift_form.cleaned_data.get('max_user_count')
shift.start_datetime = shift_form.cleaned_data.get('start_time')
shift.end_datetime = shift_form.cleaned_data.get('end_time')
shift.schedule = schedule
shift.save()
messages.success(request, 'Zeitplan & Schichten angelegt.')
return redirect('shifter:crew_view', crew_id=crew_id)
else:
messages.error(request, 'Fehler')
return render(request, 'schedule_add2.html', {'form': form, 'formset': ShiftFormSet, 'title':"Zeitplan hinzufügen"})
else:
return redirect('shifter:index')
forms.py
class ScheduleForm(forms.ModelForm):
name = forms.CharField(max_length=30, required=True, help_text='', label="Name")
sub_period = forms.ModelChoiceField(queryset=SubPeriod.objects.all(), empty_label=None, label="Tag")
location = forms.ModelChoiceField(queryset=Location.objects.all(), empty_label=None, label="Einsatzort")
class Meta:
model = Schedule
fields = ('name', 'sub_period', 'location',)
class ShiftForm(forms.ModelForm):
min_user_count = forms.IntegerField(required=True, help_text='', label="Min Count", initial=2)
max_user_count = forms.IntegerField(required=True, help_text='', label="Max Count", initial=4)
start_time = forms.DateTimeField(required=True, help_text='', label="Shift start", initial=datetime.now)
end_time = forms.DateTimeField(required=True, help_text='', label="Shift end", initial=datetime.now)
class Meta:
model = Shift
fields = ('start_time','end_time','min_user_count','max_user_count',)
Template
<form method="post">
{% csrf_token %}
{% 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 %}
{{ 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 %}
{% endfor %}
<h2 class="mt-5">Shifts</h2>
<table class="table">
{{ formset.management_form }}
{% for form in formset.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
<th></th>
</tr>
</thead>
{% endif %}
<tr class="formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{% if form.is_bound %}
{% if form.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in form.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 %}
</td>
{% endfor %}
<td></td>
</tr>
{% endfor %}
</table>
<button type="submit" class="btn btn-primary">Save</button>
</form>
Thanks in advance,
Christopher
You're returning the class, ShiftFormSet, to the template (in the third-from-last line of your code) instead of the instance, shift_formset.

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

How do I hide the field label for a HiddenInput widget in Django Admin?

I've got a bit of Django form code that looks like this:
class GalleryAdminForm(forms.ModelForm):
auto_id=False
order = forms.CharField(widget=forms.HiddenInput())
And that makes the form field go away, but it leaves the label "Order" in the Django admin page. If I use:
order = forms.CharField(widget=forms.HiddenInput(), label='')
I'm still left with the ":" between where the field and label used to be.
How do I hide the whole thing?!
Oraculum has got it right. You shouldn't be cleaning this up on the client side. If it is clutter, then you shouldn't be sending it to client at all. Building on Oraculum's answer, you should use a custom form template because you you probably still want the hidden values in the form.
{% for field in form.visible_fields %}
<div>
{{ field.errors }}
<span class="filter-label">{{ field.label_tag }}</span><br>
{{ field }}
</div>
{% endfor %}
{% for field in form.hidden_fields %}
<div style="display:none;">{{ field }}</div>
{% endfor %}
Using a custom form template to control hidden fields is cleaner because it doesn't send extraneous info to the client.
I can't believe several people have suggested using jQuery for this...
Is it a case of: when the only tool you know is a hammer everything looks like a nail?
Come on, if you're going to do it from the client-side (instead of fixing the source of the problem in the back-end code) surely the right place to do it would be in CSS?
If you're in the admin site then it's a bit harder but if it's a regular page then it's easy to just omit the whole label from the form template, for example
If you're in the admin site then you could still override the as_table, as_ul, as_p methods of BaseForm (see django/forms/forms.py) in your GalleryAdminForm class to omit the label of any field where the label is blank (or == ':' as the value may be at this stage of rendering)
(...looking at lines 160-170 of forms.py it seems like Django 1.2 should properly omit the ':' if the label is blank so I guess you're on an older version?)
Try
{% for field in form.visible_fields %}
I think it's simpler to achieve the ":" label omission for HiddenInput widget by modifying class AdminField(object) in contrib/admin/helpers.py from :
if self.is_checkbox:
classes.append(u'vCheckboxLabel')
contents = force_unicode(escape(self.field.label))
else:
contents = force_unicode(escape(self.field.label)) + u':'
to :
if self.is_checkbox:
classes.append(u'vCheckboxLabel')
contents = force_unicode(escape(self.field.label))
else:
contents = force_unicode(escape(self.field.label))
#MODIFIED 26/10/2009
if self.field.label <> '':
contents += u':'
# END MODIFY
Check the answer at Create a hidden field in the admin site, it can be done without JavaScript by overriding admin/includes/fieldset.html From there, you can inject a CSS class, and do the rest.
In theory, you should be able to pass label_suffix into the form constructor. However, the Django admin ignores this.
You've been bitten by two bugs in Django: #18134 'BoundField.label_tag should include form.label_suffix' (fixed in trunk, should be in 1.6) and to a lesser extent #11277 Hidden fields in Inlines are displayed as empty rows.
Currently, the best solution is to override the admin fieldset template. Use a HiddenInput for your widget, then override the admin fieldset template (documented here). Just create a templates/admin/includes/fieldset.html with the following contents:
<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 %}
{% for line in fieldset %}
<div class="form-row{% if line.fields|length_is:'1' and line.errors %} errors{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
{% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
{% for field in line %}
<div{% if not line.fields|length_is:'1' %} class="field-box{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}"{% endif %}>
{% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %}
{% if field.is_checkbox %}
{{ field.field }}{{ field.label_tag }}
{% else %}
{# only show the label for visible fields #}
{% if not field.field.is_hidden %}
{{ field.label_tag }}
{% endif %}
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
{% else %}
{{ field.field }}
{% endif %}
{% endif %}
{% if field.field.help_text %}
<p class="help">{{ field.field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
</div>
{% endfor %}
</fieldset>
Based upon the solution by Wilfried Hughes I 've changed the fieldset.html with little improvements.
The code snippet below not only hides the input element instead if the fieldset contains only one single element which input-type is set to hidden it also hides the surrounding div-elements wasting no space in the form.
<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 %}
{% for line in fieldset %}
<div class="form-row{% if line.fields|length_is:'1' and line.errors %} errors{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}"{% if line.fields|length_is:'1' %}{% for field in line %}{% if field.field.is_hidden %} style="display: none"{% endif %}{% endfor %}{% endif %}>
{% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
{% for field in line %}
<div{% if not line.fields|length_is:'1' %} class="field-box{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}"{% endif %}{% if field.field.is_hidden %} style="display: none"{% endif %}>
{% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %}
{% if field.is_checkbox %}
{{ field.field }}{{ field.label_tag }}
{% else %}
{# only show the label for visible fields #}
{% if not field.field.is_hidden %}
{{ field.label_tag }}
{% endif %}
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
{% else %}
{{ field.field }}
{% endif %}
{% endif %}
{% if field.field.help_text %}
<p class="help">{{ field.field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
</div>
{% endfor %}
The following removes the ':' from all your form fields. I've only tried it with the forms.Form class, but I believe it should work for forms.ModelForm too.
In Django forms, the ':' after the labels is the label_suffix. You can change or remove the label_suffix by creating a subclass of ModelForm, here called UnstyledForm, and redefining the initialization function with label_suffix set to an empty string. Then use your new UnstyledForm class.
class UnstyledForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
kwargs.setdefault('label_suffix', '')
super(UnstyledForm, self).__init__(*args, **kwargs)
class GalleryAdminForm(UnstyledForm):
auto_id=False
order = forms.CharField(widget=forms.HiddenInput())
I hope that helps!
Another way to do it, but i think it still better to iterate form.visible_fields & form.hidden_fields
<form action="{% url 'some_url' param %}" method="POST">
{% csrf_token %}
<div class="row">
{% for field in form %}
{% if not field.is_hidden %}
<div class="col-md-6">
{{ field.label_tag }}
{{ field.error }}
{{ field }}
</div>
{% else %}
{{ field }}
{% endif %}
{% endfor %}
</div>
</form>
If you're using JQuery this should do the trick:
Your form
TO_HIDE_ATTRS = {'class': 'hidden'}
class GalleryAdminForm(forms.ModelForm):
auto_id=False
order = forms.CharField(widget=forms.TextInput(attrs=TO_HIDE_ATTRS))
Javascript code to add to your template
$(document).ready(function(){
$('tr:has(.hidden)').hide();
});
That works if you're rendering your form as a table. If you want to make it work with any kind of form rendering you can do as follows:
$(document).ready(function(){
$('{{ form_field_container }}:has(.hidden)').hide();
});
And add form_field_container to your template context. An example:
If you render your form like this:
<form>
<span>{{ field.label_tag }} {{ field }}</span>
</form>
Your context must include:
'form_field_container': 'span'
You get the idea...

Categories

Resources