I have a form to perform searching. As I am using the primary key to search, The searching process is completed successfully BUT I used to get an error below the text field saying Invoice number already exists. I did some tweaks and stopped the form from showing errors but the text field still has a red outline whenever I perform the searching operation. How can I stop the form from doing that?
The code in the forms.py that disabled the form to show field errors:
class InvoiceSearchForm(forms.ModelForm):
generate_invoice = forms.BooleanField(required=False)
class Meta:
model = Invoice
fields = ['invoice_number', 'name','generate_invoice']
def __init__(self, *args, **kwargs):
super(InvoiceSearchForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_show_errors = False
self.helper.error_text_inline = False
self.form_error_title=False
The HTML code that deals with the search operation:
<div class="myForm">
<form method='POST' action=''>{% csrf_token %}
<div class="row">
<div class='col-sm-12'>
<div class="form-row">
<div class="form-group col-md-3">
{{ form.invoice_number|as_crispy_field }}
</div>
<div class="form-group col-md-3">
{{ form.name|as_crispy_field }}
</div>
<div class="form-group col-md-3">
{{ form.generate_invoice|as_crispy_field }}
</div>
<div class="form-group col-md-3">
<br>
<button type="submit" class="btn btn-primary">Search</button>
</div>
</div>
</div>
</div>
</form>
</div>
The views.py related to the search operation:
#login_required
def list_invoice(request):
title = 'List of Invoices'
queryset = Invoice.objects.all()
form = InvoiceSearchForm(request.POST or None)
context = {
"title": title,
"queryset": queryset,
"form":form,
}
if request.method == 'POST':
queryset = Invoice.objects.filter(invoice_number__icontains=form['invoice_number'].value(),name__icontains=form['name'].value())
context = {
"form": form,
"title": title,
"queryset": queryset,
}
return render(request, "list_invoice.html", context)
The red outline of the textbox that I get after performing search operation->
I think you need to use forms.Form instead of forms.ModelForm which is designed for creating and updating Model instances.
Related
I am trying to create a page with formset in it. So far I've gotten the following:
forms.py
class ContractorForm(forms.ModelForm):
class Meta:
model = Contractor
fields = [
'first_name', 'last_name', 'email', 'company_name',
]
views.py
class ContractorUpdateView(SimpleLoginRequiredMixin, TemplateView):
def get(self, request, *args, **kwargs):
"""Handle GET requests: instantiate a blank version of the form."""
ContractorFormSet = formset_factory(
Contractor)
contractor_formset = ContractorFormSet()
context = {"contractor_formset": contractor_formset}
return render(
request, "accounts/contractor_form.html", context)
contractor_form.html
<div class="card-body">
<form class="" method="post" action="" id="facility_contractor_form">
{% for form in contractor_formset %}
{% csrf_token %}
{{ form.as_p }}
{% endfor %}
</form>
</div>
<!-- /.card-body -->
<div class="card-footer">
Cancel
<input type="submit" form="facility_contractor_form" value="Save Changes"
class="btn btn-success float-right">
</div>
But when I try to open the page, I'll get the following error:
TypeError at /facility/2/contractor/
Contractor() got an unexpected keyword argument 'auto_id'
Any ideas? I think my using for maybe the wrong idea
Your ContractorUpdateView references the model, while it should reference the form, so it gotta be:
ContractorFormSet = formset_factory(ContractorForm)
I have searched the site for a solution, many related questions, but no direct response given. I have 3 apps on my projects, and 2 worked pretty well, except for this app, which is not writing to the database.
Yes, the other 2 apps write to the postgres database, and I can view the table, but this return empty rows, and I don't see any problem. I hope someone can help me, see below my Model, Form and View.py.
MY View.py
from django.shortcuts import render, redirect
from .forms import EngForm
def EngineerList(request):
return render(request, "Engineers/elist.html")
def EngineerForm(request):
if request.method == "GET":
form = EngForm()
return render(request, "Engineers/eform.html", {'form':form})
else:
form = EngForm(request.POST)
if form.is_valid():
form.save()
return redirect('/engineer/') #pointing to urls.py paths
My Forms.py
from django import forms
from .models import Engineers
class EngForm(forms.ModelForm):
class Meta:
model = Engineers
fields = '__all__'
labels = {
'workarea' : 'Zone',
'face' : 'Picture',
}
def __init__(self, *args, **kwargs):
super(EngForm, self).__init__(*args, **kwargs)
self.fields['position'].empty_label='Select'
self.fields['workarea'].empty_label='Select'
self.fields['face'].required = False
My Model.py
from django.db import models
class Engineers(models.Model):
position = (
('NOC', 'NOC'),
('Supervisor', 'Supervisor'),
('Site Manager','Site Manager'),
('Site Engineer', 'Site Engineer'),
)
region = (
('SS','South-South'),('SW','SW'),('SE','SE'),
('NE','NE'),('NW','NW'),('NC','NC'),
)
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
email = models.EmailField(max_length=50)
username = models.CharField(max_length=20)
phone = models.IntegerField()
position = models.CharField(max_length=20, choices=position)
workarea = models.CharField(max_length=20, choices=region)
face = models.ImageField(upload_to='', height_field=15, width_field=9)
My HTML
{% extends "Dashboard/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST" action="" autocomplete="off">
{% csrf_token %}
<div class="row">
<div class="col-md-12">
{{form.face|as_crispy_field}}
</div>
<p>
<hr>
<p>
<div class="col-md-6">
{{form.firstname|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.lastname|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.username|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.position|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.phone|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.workarea|as_crispy_field}}
</div>
<div class="col-md-12">
{{form.email|as_crispy_field}}
</div>
</div>
<hr>
<div>
<button type="submit" class="btn btn-success"><i class="fas fa-save"></i> Submit</button>
</div>
</form>
{% endblock content %}
My problem is, the database table is returning empty row.
Solved. Applied #GwynBleidD suggest, I reviewed the doc, and then rearranged the code as such.
def EngineerForm(request):
if request.method == "POST":
form = EngForm(request.POST)
if form.is_valid():
form.save()
return redirect('/engineer/') #pointing to urls.py paths
else:
form = EngForm()
return render(request, "Engineers/eform.html", {'form':form})
I've created a template for updating account profiles using a Bootstrap snippet (from https://www.bootdey.com). With the django default format (like {{ form.as_p }}), updating accounts works (for example, when I modify the first name, it changes in the database). When I use the bootstrapp snippet, it doesn't update: it goes straight to 'homepage' without updating (as explained in views.py).
In forms.py
class EditAccountForm(UserChangeForm):
class Meta:
model = Account
fields = ('email','first_name','last_name')
In views.py
def EditProfile(request):
context= {}
if request.POST:
form = EditAccountForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
email = form.cleaned_data.get("email")
raw_password = form.cleaned_data.get("password1")
account = authenticate(email=email,password=raw_password)
return redirect('profile_page')
else:
context['edit_form'] = form
return redirect('homepage')
else:
form = EditAccountForm(instance=request.user)
context['edit_form'] = form
return render(request,'Account/edit_page.html',context)
the template: edit_profile.html (I only show the first_name part as example)
<form method = "POST" class="form" novalidate="">
{% csrf_token %}
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<div class="form-group">
<label>First name</label>
<input class="form-control" type="text" name="firstna" value={{ edit_form.first_name.value }}>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col d-flex justify-content-end">
<button class="btn btn-primary" type="submit">Save Changes</button>
PS: I've preferred to use those snippets instead of the Django style since I find them more attractive and offer more freedom.
Please check you are taking same value if you are changing the data in views like if you are using (name="firstna") in template so for First Name you have to take same in views.
Same question is asked here you can go and follow below link
[How to update user profile in Django
I'm not sure where I'm going wrong with the form validation... I also want to display error messages wether the for was submitted successfully or not.
Currently, I'm using a DetailView, where a person can fill in a BookingForm()
forms.py
from django.core.validators import RegexValidator
class BookingForm(forms.Form):
Name = forms.CharField()
Postcode = forms.CharField(max_length=8,label='Postcode')
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
Phone = forms.CharField(max_length=15,validators=[phone_regex],label='Phone')
Date = forms.CharField(max_length=30,label='Date')
Time = forms.CharField(max_length=10,label='Time')
In my views.py I defined def post to allow post requests. However, I always get the ELSE loop returned
def post(self,request,**kwargs):
# put your own credentials here
form = BookingForm(self.request.POST)
if form.is_valid():
user_phone = form.cleaned_data['Phone']
postcode = form.cleaned_data['Postcode']
date = form.cleaned_data['Date']
account_sid = "***"
auth_token = "***"
found = Model.objects.get(id=self.kwargs['pk'])
client = Client(account_sid, auth_token)
client.messages.create(
to=Model.phone_number,
from_="+442033225719",
body="You have a new booking." +
"Call phone number:{}. Address: {}. Date:{}"
.format(user_phone,postcode,date))
messages.success(request, 'Your booking was reserved.')
else:
messages.error(request, 'Error occurred.')
return redirect('users:detail', pk=self.kwargs['pk'])
And my model_detail.html which handles the form.
FURTHER EDIT:
I created the following HTML template which I include in the main template using {% include 'booking_form.html' %}:
<!-- Book Now -->
<form action="" method="post">
{{ form.non_field_errors }}
{% csrf_token %}
<div class="boxed-widget">
<h3><i class="fa fa-calendar-check-o "></i> Book Now</h3>
<div class="row with-forms margin-top-0">
<div class="col-lg-6 col-md-12">
{{ form.name.errors }}
<label for="{{ form.name.id_for_label }}">Full Name:</label>
{{ form.name }}
</div>
<div class="col-lg-6 col-md-12">
{{ form.postcode.errors }}
<label for="{{ form.postcode.id_for_label }}">Postcode:</label>
{{ form.postcode }}
</div>
</div>
<div class="row with-forms margin-top-0">
<div class="col-lg-12 col-md-12">
{{ form.name.errors }}
<label for="{{ form.name.id_for_label }}">Full Name:</label>
{{ form.name }}
</div>
</div>
<div class="row with-forms margin-top-0">
<div class="col-lg-6 col-md-12">
{{ form.date.errors }}
<input name="Date" type="text" id="booking-date" data-lang="en" data-large-mode="true" data-min-year="2017" data-max-year="2020">
</div>
<div class="col-lg-6 col-md-12">
{{ form.time.errors }}
<input name="Time" type="text" id="booking-time" value="9:00 am">
</div>
</div>
<!-- progress button animation handled via custom.js -->
<button type="submit" class="progress-button button fullwidth margin-top-5"><span>Book Now</span></button>
</div>
</form>
<!-- Book Now / End -->
My BookingForm in forms.py has remained unchanged. However, now, I see no fields to input. I'm assuming this is because the form is not passed into the template.
Full content of my views.py of the DetailView:
class TeacherView(generic.DetailView,FormMixin):
model = Teacher
form_class = BookingForm
def post(self,request,**kwargs):
form = BookingForm(self.request.POST)
if form.is_valid():
user_phone = form.cleaned_data['Phone']
account_sid = "***"
auth_token = "***"
teacher = Teacher.objects.get(id=self.kwargs['pk'])
client = Client(account_sid, auth_token)
client.messages.create(
to=teacher.phone_number,
from_="+442033225719",
body=""
messages.success(request, 'Success Message')
return redirect('users:index')
else:
messages.error(request, 'Error occured.')
return redirect("users:index")
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(TeacherView, self).get_context_data(**kwargs)
# Add extra context from another model
context['form'] = self.get_form()
return context
You're always redirecting, whether the form is valid or not, so obviously you can't have the form errors displayed. If you want the form errors to be shown in your template, you need to render the template and return it as response when the validation fail - example with a plain function-based view (if you insist on using generic class-based views then use a FormMixin with your DetailView):
def myview(request, ...):
if request.method == "POST":
form = MyForm(request.POST):
if form.is_valid():
handle_the_form(...)
messages.success(request, "success message here")
return redirect(where you want to redirect)
else:
# GET, display an empty form
form = MyForm()
return render(request, "mytemplate.html", context={"form":form})
Also in your template you need to use the form itself instead of hardcoding it, as explained here in the FineManual.
wrt/ the messages framework's messages not displaying either, this is certainly a configuration issue, so re-read the messages doc and check your settings etc.
Hi i am relatively new to Django. I am currently trying to store values into database. Timesheet.html is basically my form and i have tried to do the validation but it doesn't work. I have searched everything i can but the data being filled out wont be saved into database. Is there anywhere to check that the checkbox has been ticked before user can submit it ?
timesheet.html
<form method="POST" onsubmit="return validation()" action="">
{% csrf_token %}
<div class="content-wrapper">
<div class="sub-content">
<div>
<p>Student ID: {{timesheet.studentID}}</p>
<input id="sid" type="field" name="studentid">
</div>
</div>
<div class="sub-content">
<div>
<p>Student Name: {{timesheet.studentName}}</p>
<input id="sname" type="field" name="studentname">
</div>
</div>
<div class="sub-content">
<div>
<p>Start Date: {{timesheet.startDate}}</p>
<input id="sdate" type="date" name="startdate">
</div>
</div>
<div class="sub-content">
<div>
<p>End Date: {{timesheet.endDate}}</p>
<input id="edate" type="date" name="enddate">
</div>
</div>
</div>
<div class="end-content">
<div class="center-align">
<div class="checklist">
<p>By checking this box I agree that I have satisfied all requirements to continue receiving my scholarship
allowance.</p>
<input id="agree" type="checkbox" name="checkbox" class="tick-att">
</div>
<br>
<div class="align-right">
<input type="submit" class="button" name="submit" value="submit" >
</div>
</div>
</div>
</form>
models.py
class Timesheet(models.Model):
studentID = models.CharField("Student ID", max_length=8, primary_key=True, default="")
studentName = models.CharField("Student Name", max_length=500, default="")
startDate = models.DateField("Start Date", max_length=8)
endDate = models.DateField("End Date", max_length=8)
def __str__(self):
return self.studentID
class TimesheetForm(forms.ModelForm):
class Meta:
model = Timesheet
fields = '__all__'
views.py
def timesheet(request):
if request.method == "POST":
form = TimesheetForm(request.POST)
if form.is_valid():
timesheet = form.save(commit=False)
timesheet.studentID = request.POST.get('studentID')
timesheet.studentName = request.POST.get('studentName')
timesheet.startDate = request.POST.get('startDate')
timesheet.endDate = request.POST.get('endDate')
timesheet.save()
return HttpResponseRedirect(reverse('hrfinance/timesheet.html'))
#if the form is not valid, redirect the student to the same page
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
There are lots of very strange things here.
Firstly, there is no need to set the fields manually on save. That is exactly what form.save() does in the first place. (And if you ever did need to set something manually, you should always get it from form.cleaned_data rather than request.POST.)
Secondly, you re-instantiate the form if it fails validation. That means that the users can never see the errors that are preventing it from validating.
Thirdly, you should show errors in the template. Along with that, you should let Django itself output your fields so that they are automatically prepopulated when the form is invalid.
Finally, you should add your checkbox as a field on the form, so that it is validated along with everything else.
class TimesheetForm(forms.ModelForm):
checkbox = forms.BooleanField()
class Meta:
model = Timesheet
fields = '__all__'
...
def timesheet(request):
if request.method == "POST":
form = TimesheetForm(request.POST)
if form.is_valid():
timesheet = form.save()
return HttpResponseRedirect(reverse('hrfinance/timesheet.html'))
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
...
<form method="POST" onsubmit="return validation()" action="">
{% csrf_token %}
{{ form.errors }}
<div class="content-wrapper">
<div class="sub-content">
<div>
<p>Student ID: {{timesheet.studentID}}</p>
{{ form.studentID }}
</div>
</div>
</div>
.... etc...
<div class="checklist">
<p>By checking this box I agree that I have satisfied all requirements to continue receiving my scholarship
allowance.</p>
{{ form.checkbox }}
</div>