When submitting a django form i am getting a ValidationError.
In my form this is my input: 01/01/2017
But django tell me that the format must be 'AAAA-MM-GG'.
With this Exception Location: /usr/local/lib/python3.5/dist-packages/django/db/models/fields/init.py in to_python, line 1271
This is the code on my project:
# models.py
class Archivio(models.Model):
sys_codice = models.AutoField(primary_key=True)
some_other_field ...
class QuoteIscrizione(models.Model):
sys_chiave = models.AutoField(primary_key=True)
sys_cod = models.ForeignKey(Archivio, on_delete=models.CASCADE)
data_quota = models.DateField(blank=True, null=True)
# forms.py
class ArchivioSearchForm(forms.Form):
data_quota = forms.DateField(widget=forms.DateInput(format='%d/%m/%Y'), input_formats=('%d/%m/%Y',), required=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self:
field.field.widget.attrs['class'] = 'form-control '
if type(field.field.widget) is DateInput:
field.field.widget.attrs['class'] += 'datepicker'
def clean(self):
data_quota = self.cleaned_data['data_quota']
return self.cleaned_data
# views.py
def ArchivioSearchView(request):
model = Archivio
form = ArchivioSearchForm()
if request.GET.get('data_quota'):
selection = Archivio.objects.filter(Q(quoteiscrizione__data_quota__gte=request.GET.get('data_quota'))
return render(request, 'search_template.html', {'selection':selection, 'form':form})
# search_template.html
<form action="" method="get" class="form-horizontal">
<div class="form-group form-group-md">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
{% for field in form %}
<div class="form-group row">
<label class="col-md-3 col-form-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="col-md-6">
{{ field.as_widget() }}
</div>
</div>
{% endfor %}
<input type="submit" value="Confermo" />
</div>
</form>
{% for select in selection %}
<h4><li>{{ select.nominativo }}</li></h4>
{% endfor %}
And I also have this on my settings.py
LANGUAGE_CODE = 'it-IT'
TIME_ZONE = 'Europe/Rome'
USE_I18N = True
USE_L10N = True
USE_TZ = True
I have tried to use on my settings.py of course after turning USE_L10N = False
DATE_INPUT_FORMATS = ['%d/%m/%Y']
I have tried also to use on my forms.py on init function on for loop:
if type(field.field.widget) is DateInput:
field.field.widget.input_formats = ['d%/%m/%Y']
I have tried not only with Lists but also with strings like this '%d/%m/%Y'.
I also see that this error occur even if my input is 2017/01/01!
I cannot figure out what I am doing wrong. Django continues expecting dates in format 'YYYY-MM-DD' even if I override every possible method or parameter of DateField's widget.
Thank to all of you that will take some of your time trying to help me!
You need to set formats on DateInput widget when you declare your variable on the form, plus input_formats, like:
data_quota = forms.DateField(widget=forms.DateInput(format ='%d/%m/%Y'), input_formats=('%d/%m/%Y',), required=False)
Related
i try to do checkboxes in form for M2M field, but have this error, have no idea how to fix it. Google didn't help me, i tried.
When i render objects as list, i can select few objects and save it, so problem is not in views.py ,but it doesn't work with checkboxes.
My code:
forms.py
class CheckoutForm(forms.ModelForm):
class Meta:
model = Checkout
fields = ('dishes', 'user')
def __init__(self, *args, **kwargs):
super(CheckoutForm, self).__init__(*args, **kwargs)
self.fields["dishes"].widget = CheckboxSelectMultiple()
self.fields["dishes"].queryset = Dish.objects.all()
so only way that i can see an form error:
render form fields - send a empty form - put back {{ form.as_p }} - i can see an error "field is required"
page.html
<form class="p-2" action="{% url 'make_order' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<select name="user">
<option value="{{ user.id }}">{{ user }}</option>
</select>
<div
class="row row-cols-1 row-cols-md-5 g-2"
style="margin-left: -40px"
>
{% for dish in dishes %}
<div class="col">
<div class="card" style="width: 14rem">
<img
class="card-img-top"
style="width: 220px; height: 240px"
src="{{ dish.image.url }}"
alt="Card image cap"
/>
<div class="card-body">
<h5 class="card-title">{{ dish.name }}</h5>
<p class="card-text">Description: {{ dish.description }}</p>
<p class="card-text">Ingredients: {{ dish.ingredients }} g</p>
<p class="card-text">Serving size: {{ dish.serving_size }} g</p>
<p class="card-text">Price: {{ dish.price }} UAH</p>
<input
type="checkbox"
class="btn btn-primary"
name="dishes"
id="{{ dish.id }}"
value="{{ dish.id }}"
/>Add to cart
</div>
</div>
</div>
{% endfor %}
<input type="submit" value="ADD" class="btn btn-primary" />
</form>
views.py
class OrderView(LoginRequiredMixin, CreateView):
model = Checkout
template_name = "food_order/make_order.html"
form_class = CheckoutForm
success_url = "/order/"
login_url = "/login/"
raise_exception = True
def form_valid(self, form):
print('i am here')
instance = form.save(commit=False)
instance.user = self.request.user
instance.save()
dishes = form.cleaned_data["dishes"]
for dish in dishes:
dish, created = Dish.objects.get_or_create(name = dish)
dish.save()
instance.dishes.add(dish)
instance.save()
print(instance.dishes)
print(instance)
form.save_m2m()
return super(OrderView, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(OrderView, self).get_context_data(**kwargs)
context["dishes"] = Dish.objects.all()
context["orders"] = Checkout.objects.all()
return context
I don't think you need to be tinkering with __init__ here when setting the widget. It may be overwriting your values for a modelform.
Try:
class CheckoutForm(forms.ModelForm):
class Meta:
model = Checkout
fields = ('dishes', 'user',)
widgets = {'dishes': forms.CheckboxSelectMultiple() }
This should work as m2m fields have the ModelMultipleChoiceField by default. If you want to make it all explicit, you can go with:
class CheckoutForm(forms.ModelForm):
dishes = forms.ModelMultipleChoiceField(
queryset=Dish.objects.all(),
widget=forms.CheckboxSelectMultiple,
)
class Meta:
model = Checkout
fields = ('dishes', 'user',)
If you are formatting the checkboxes by hand
make sure they have name="dishes" (assuming dishes is the name of the field in your Checkout model) and value="<the dish id>"
You may also need to grab the values submitted with request.POST.getList('dishes'), otherwise you will ony get one value submitted
Am trying to customize my checkbox inputs to look like this [what i want to archive]
so i tried this...
profile.html
<ul class="wt-accountinfo">
{% for key, value in form.interests.field.choices %}
<li>
<div class="wt-on-off pull-right">
<input type="checkbox" id="{{ value }}" value="{{ key }}" name="interests">
<label for="{{ value }}"><i></i></label>
</div>
<span>{{ value | title }}</span>
</li>
{% endfor %}
</ul>
which renders the html fine but highlight the select fields from the database
but using {{ form.interest }} highlights the selected checked boxes from the database
here is the forms.py
class ProfileForm(forms.ModelForm):
interests = forms.ModelMultipleChoiceField(
queryset=JobsCategories.objects.all(), widget=forms.CheckboxSelectMultiple(),
required=False
)
class Meta:
model = Profile
fields = ['interests']
and here is the models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
interests = models.ManyToManyField(Categories, related_name='interests', null=True, blank=True)
def __str__(self):
return f'{self.user.first_name} {self.user.last_name}'
in the views.py
def dashboard_profile(request):
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES, instance=request.user.profile)
account_form = AccountForm(request.POST, instance=request.user)
if form.is_valid() and account_form.is_valid():
f_interests = form.save(commit=False)
for i in request.POST.getlist('interest'):
f_interests.interest.update(i)
f_interests.save()
form.save_m2m()
account_form.save()
return redirect('index')
else:
form = ProfileForm(instance=request.user.profile)
account_form = AccountForm(instance=request.user)
context = {
'form': form,
'account_form': account_form,
}
return render(request, 'dashboard_profile.html', context)
NOTE!!! if i select the options i want and click save, it saves the options i checked to the database
this is it
this is it in the admins section
admin section
admin section 2
and also when i use {{ form.interests }} in the the template it renders fine and highlights the checked option from the database but its not styled
[how it looks like when i use {{ form.interests }}]
i know am missing somtehing in the profile.html so please help me out Thanks.
You're missing logic within your input tag to apply the existing value of the field choice.
<ul class="wt-accountinfo">
{% for key, value in form.interests.field.choices %}
<li>
<div class="wt-on-off pull-right">
<input type="checkbox"
id="{{ value }}"
value="{{ key }}"
name="interests"
{% if value %}checked{% endif %}>
<label for="{{ value }}"><i></i></label>
</div>
<span>{{ value | title }}</span>
</li>
{% endfor %}
</ul>
Hi so basically I am trying to populate a drop-down menu from a database I currently have. This will enable a 'Teacher' to select a 'Student' they input grades for. I am struggling to understand any of the tutorials online due to most of them being for django 1.9 whereas I am using 2.1.
Please if you could help, it would be much appreciated.
Template:
<form action="{% url 'subject1_view' %}" method="post">
{% csrf_token %}
<div class="form-group row">
<label class="col-2 col-form-label" for="information">Student Name</label>
<div class="col-10">
<form method="POST">
<select class="form-control" name="student_name" id="information">
{% for ?? %}
<option value="{{ ?? }}">{{ ?? }}</option>
{% endfor %}
</select>
</form>
</div>
</div>
URLs:
from django.urls import path, include
from . import views
urlpatterns = [
path('teacher_login', views.teacher_login, name='teacher_login'),
path('t_dashboard', views.t_dashboard, name='t_dashboard'),
path('subject1_view', views.subject1_view, name='subject1_view'),
path('loguserout', views.loguserout, name='loguserout'),
]
Views:
def subject1_view(request):
if request.method == 'POST':
student_name = (request.POST.get('student_name'))
current_grade = (request.POST.get('current_grade'))
previous_grade = (request.POST.get('previous_grade'))
target_grade = (request.POST.get('target_grade'))
incomplete_homework = (request.POST.get('incomplete_homework'))
behaviour_rank = (request.POST.get('behaviour_rank'))
i = Subject1(student_name=student_name, current_grade=current_grade, previous_grade=previous_grade,
target_grade=target_grade, incomplete_homework=incomplete_homework, behaviour_rank=behaviour_rank)
i.save()
return render(request, 'Teacher/dashboard.html')
else:
return render(request, 'Teacher/subject1.html')
Models:
from django.db import models
from Student.models import Student
# Create your models here.
class Subject1(models.Model):
student_name = models.ForeignKey(Student, on_delete=models.CASCADE)
current_grade = models.CharField(max_length=2)
previous_grade = models.CharField(max_length=2)
target_grade = models.CharField(max_length=2)
incomplete_homework = models.CharField(max_length=2)
behaviour_rank = models.CharField(max_length=2)
def __str__(self):
return self.student_name
Use a Django Form, and populate the choices on the form's init method:
class SelectForm(forms.Form):
student = forms.ChoiceField(widget=forms.Select(attrs={'class': 'form-control'}))
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['student'].choices= [(student.id, student.name) for student in Student.objects.all()]
Template:
<form action="{% url 'subject1_view' %}" method="post">
{% csrf_token %}
<div class="form-group row">
<label class="col-2 col-form-label" for="information">Student Name</label>
<div class="col-10">
{{ form }}
</div>
</div>
</form>
Also add add form to context from View.
I am trying to fill out a form in my Django web application and post it. It is giving me an error
object Application has no attribute cleaned_data
I looked around Stack Overflow at similar questions, but the resolutions for others are not issues with my code. Here is my view:
def single_career(request, a_slug):
a_slug = a_slug.strip('/')
try:
career = Career.objects.get(slug=a_slug)
except:
career = None
if request.method == "POST":
form = Application(request.POST, request.FILES)
Post = True
if form.is_valid():
cleaned_data = Application.cleaned_data
is_valid = True
clean_first = cleaned_data['first_name']
clean_last = cleaned_data['last_name']
clean_email = cleaned_data['email']
clean_phone = cleaned_data['phone']
clean_file = cleaned_data['resume']
clean_message = cleaned_data['message']
date = datetime.datetime.now()
else:
is_valid = False
else:
form = Application()
Post = False
is_valid = False
context = {'career': career, 'form': form, 'post': Post, 'is_valid': is_valid}
template = 'overrides/careers.html'
set_detail_context(request, context)
return render_to_response(template, context, context_instance=RequestContext(request))
the html:
<form action="" method="POST" enctype="multipart/form-data" class="application-form">
{% csrf_token %}
<div class="firstname">
<p>FIRST NAME</p>
{{ form.first_name }}
</div>
<div class="lastname">
<p>LAST NAME</p>
{{ form.last_name }}
</div>
<div class="email">
<p>EMAIL</p>
{{ form.email }}
</div>
<div class="phone">
<p>PHONE</p>
{{ form.phone }}
</div>
{# form fileupload-input is hidden, and extra readonly text-input is there #}
{# to be able to override the styling of the fileupload-input button #}
<div>
<p>ATATCH PDF RESUME</p>
<input class="readonly" type="text" READONLY>
<div class="resume">
{{ form.resume }}
<div>
<a id="browse">BROWSE</a>
</div>
</div>
</div>
<div>
<p>MESSAGE</p>
{{ form.message }}
</div>
<button class="submit-button" type="submit">
APPLY
</button>
</form>
and the form class:
from django import forms
class Application(forms.Form):
first_name = forms.CharField(label="First Name", max_length=50)
last_name = forms.CharField(label="Last Name", max_length=50)
email = forms.EmailField(label="Email", max_length=80)
phone = forms.CharField(label="Phone Number", max_length=30)
resume = forms.FileField(label="Resume", max_length=1000)
message = forms.CharField(label="Message", max_length=800, widget=forms.Textarea)
The validated form is form, not Application.
The cleaned_data belongs to the form instance. You should have:
if form.is_valid():
cleaned_data = form.cleaned_data
You are getting the error because you are trying to fetch it from the form class.
if form.is_valid():
cleaned_data = Application.cleaned_data
I'm trying to create a TimeInput field in a form and noticed that the widget isn't showing correctly. But when I check the localhost:8000/admin, I see the widget showing up correctly.
My code is as follows. For models.py,
class TimeLimit(models.Model):
before = models.TimeField(blank=True, default=time(7, 0)) # 7AM
after = models.TimeField(blank=True, default=time(23, 0)) # 11PM
For views.py,
class UpdateTimeLimitView(LoginRequiredMixin, FormView):
model = TimeLimit
template_name = 'accounts/update_time_limit.html'
form_class = UpdateTimeLimitForm
def get_success_url(self):
return reverse_lazy('accounts:user_profile') + '?username=' + self.request.GET['username']
def get_context_data(self, **kwargs):
data = super(UpdateTimeLimitView, self).get_context_data(**kwargs)
data['username'] = self.request.GET['username']
return data
For forms.py,
class UpdateTimeLimitForm(forms.Form):
time_error = {'required': 'This field is required.',
'invalid': 'Please enter valid Hour:Minute values.'}
before = forms.TimeField(widget=forms.TimeInput(format='%H:%M'))
after = forms.TimeField(widget=TimeInput(format='%H:%M'))
class Meta:
model = TimeLimit
Finally, the relevant part for fields in update_time_limit.html,
<div class="container">
<form method="post">
{% csrf_token %}
<p>
{% for field in form %}
{{ field.errors }}
<label for="{{ field.id_for_label }}">{{ field.label }}({{ field.help_text }}):</label>
<br />
{{ field }}<br /><br /> and
{% endfor %}
</p>
<input class="btn btn-primary done-btn" type="submit" value="Update Time Limit">
</form>
</div>
Is there anything that I'm missing or doing wrong? Thank you.
The Django admin uses AdminTimeWidget to display time fields, not the TimeInput widget that you are using in your code.
There isn't a documented way to reuse the AdminTimeWidget outside of the Django admin. Getting it to work is very hacky (see the answer on this question, which is probably out of date), so it's probably better to use a different widget.
convert datetime.time(7, 0) to string work for me.
data['before'] = data['before'].strftime('%H:%M:%S')