Django form ValidationError - python

I have two forms in a view. One htlm form includes form and formset, other html form includes just single form.
When I am trying to submit singe form (Reminder), I am getting this error:
[u'ManagementForm data is missing or has been tampered with']
View:
form_class = CreateEventForm
second_form_class = modelformset_factory(EventTime, form = EventTimeForm, extra=3, formset=EventTimeFormset)
third_form_class = Reminder
model = Event
template_name = 'eventAdmin.html'
def get_context_data(self, **kwargs):
context = super(EventAdminPage, self).get_context_data(**kwargs)
context['form'] = self.form_class(self.request.POST or None, prefix="form", instance = self.object)
context['formset'] = self.second_form_class(
self.request.POST or None,
prefix="formset",
queryset=context['event_times'])
context['reminder_form'] = Reminder(self.request.POST or None)
return context
def post(self, request, **kwargs):
self.object = self.get_object()
event_times = EventTime.objects.filter(event = self.object).exclude(start_time = None)
if 'update_event_form' in request.POST:
form_class = self.get_form_class()
form = self.form_class(request.POST, prefix="form", instance=self.get_object())
formset = self.second_form_class(request.POST, prefix="formset", queryset=event_times)
if form.is_valid() and formset.is_valid():
event = form.save()
event_times = formset.save()
return HttpResponseRedirect('/event-admin-%s' %self.kwargs['event_id'])
else:
return self.render_to_response(
self.get_context_data(form=form, formset=formset))
if 'reminder_form' in request.POST:
form_class = self.second_form_class
form_name = 'Reminder'
form = form_class(request.POST)
if form.is_valid():
form.save(commit=False)
message = form.cleaned_data.get('text')
return HttpResponseRedirect('/event-admin-%s' %self.kwargs['event_id'])
else:
return self.render_to_response(
self.get_context_data(form=form))
HTML of form that raises error:
<form method='POST' action=''><input type='hidden' name='csrfmiddlewaretoken' value='3uQyEn4m8bHpM7Jy6a8WKQz5A8Uf6RZF' />
<div id="div_id_text" class="form-group"> <label for="id_text" class="control-label requiredField">
Text<span class="asteriskField">*</span> </label> <div class="controls "> <textarea class="textarea form-control" cols="40" id="id_text" maxlength="500" name="text" rows="10">
</textarea> </div> </div>
<input class="btn btn-primary" type="submit" name="reminder_form" value="Send" />
</form>

You need to add this line {{ form.management_form }} after the <form method='POST' action=''>. This is used by Django to manage the forms within the formset.
<form method='POST' action=''>
{{ form.management_form }}
<input type='hidden' name='csrfmiddlewaretoken' value='3uQyEn4m8bHpM7Jy6a8WKQz5A8Uf6RZF' />
<div id="div_id_text" class="form-group">
<label for="id_text" class="control-label requiredField">
Text
<span class="asteriskField">*</span>
</label> <div class="controls ">
<textarea class="textarea form-control" cols="40" id="id_text" maxlength="500" name="text" rows="10">
</textarea>
</div>
</div>
<input class="btn btn-primary" type="submit" name="reminder_form" value="Send" />
</form>

Related

Django form doesn't send data

I am trying to add a user to some events in the calendar (using fullcalendar), but when putting the form to request the data from the user, this form does not send me the data. How can I get the data it is supposed to send?
This is my event_register.html:
<div class="col-xl-6">
<p>Apuntarse como invitado.</p>
<form action="" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="first_name">Nombre:</label>
<!--<input id="first_name" name="first_name" placeholder="Nombre del participante" type="text" required="required" class="form-control">-->
<div class="input-group">
{{form.first_name}}
</div>
</div>
<div class="form-group">
<label for="last_name">Apellidos:</label>
<!--<input id="last_name" name="last_name" placeholder="Apellidos del participante" type="text" required="required" class="form-control">-->
<div class="input-group">
{{form.last_name}}
</div>
</div>
<div class="form-group">
<label for="phone">Teléfono:</label>
<!--<input id="phone" name="phone" placeholder="Teléfono del participante" type="text" required="required" class="form-control">-->
<div class="input-group">
{{form.phone}}
</div>
</div>
<div class="form-group">
<label for="email">Correo electrónico:</label>
<!--<input id="email" name="email" placeholder="Correo electrónico del participante" type="text" required="required" class="form-control">-->
<div class="input-group">
{{form.email}}
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary btn-block py-2" value="Enviar">
</div>
</form>
</div>
<div class="col-xl-6">
</div>
This is my view.py:
def attend_to(request):
event_form = EventForm()
print('Hola')
if request.method == 'POST':
event_form = EventForm(data=request.POST)
if event_form.is_valid():
Assistant.objects.create(UserManegement=None, Event=request.event_id, frist_name=request.POST["first_name"], last_name=request.POST["last_name"], phone=request.POST["phone"], email=request.POST["email"])
return render(request, "core/home.html")
else:
Assistant.objects.create(UserManegement=request.POST["user"], Event=request.POST["event"])
return render( "core/home.html")
This is my forms.py:
from django import forms
class EventForm(forms.Form):
first_name = forms.CharField(label="first_name", required=True, widget=forms.TextInput(
attrs={'class':'form-control', 'placeholder':'Escribe tu nombre'}
), min_length=3, max_length=100)
last_name = forms.CharField(label="last_name", required=True, widget=forms.TextInput(
attrs={'class':'form-control', 'placeholder':'Apellidos'}
), min_length=3, max_length=100)
phone = forms.CharField(label="phone", required=True, widget=forms.TextInput(
attrs={'class':'form-control', 'placeholder':'Telefono'}
), min_length=9, max_length=9)
email = forms.EmailField(label="Email", required=True, widget=forms.EmailInput(
attrs={'class':'form-control', 'placeholder':'Escribe tu email'}
), min_length=3, max_length=100)
This is my urls.py:
urlpatterns = [
path('', views.attend_to, name='attend_to'),
]
And this is what I receive when clicking on the button:
"POST /event/1/ HTTP/1.1" 200 6249
This is the view that renders the event_register.html view, I have a calendar with fullcalendar and when clicking on an event it shows me that template.
def register_event(request, event_id):
event = get_object_or_404(Event, id=event_id)
return render(request, "events/event_register.html", {'event':event})
Thanks in advance.
Edit 1:
I don't know what the problem is now, but when I click on the event to open the url that contains the form, it doesn't show me the corresponding template. It is as if it did not enter the if request.method == 'POST'. Here I leave the updated code.
The view what renders the template event_register.html:
def register_event(request, event_id):
event_form = EventForm()
event = get_object_or_404(Event, id=event_id)
return render(request, "events/event_register.html", {'event':event,
'form':event_form})
The template what contains the form:
<form action="{% url 'attend_to' %}" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="first_name">Nombre:</label>
<!--<input id="first_name" name="first_name" placeholder="Nombre del participante" type="text" required="required" class="form-control">-->
<div class="input-group">
{{form.frist_name}}
</div>
</div>
urls.py core to load the template:
urlpatterns = [
#Path del core
path('', views.home, name='home'),
path('about/', views.about, name='about'),
path('event/<int:event_id>/', include('events.urls'), name='attend_to'),
]
urls.py for events:
urlpatterns = [
path('', views.attend_to, name='attend_to'),
]
The views.py what contains attend_to, it's show me the print('Hola'):
def attend_to(request, event_id):
event_form = EventForm()
print('Hola')
if request.method == 'POST':
event_form = EventForm(request.POST)
if event_form.is_valid():
event_form.save()
context = {"form":event_form}
Assistant.objects.create(UserManegement=None, Event=request.event_id, frist_name=context.first_name, last_name=context.last_name, phone=context.phone, email=context.email)
#Assistant.objects.create(UserManegement=None, Event=request.event_id, frist_name=request.POST["first_name"], last_name=request.POST["last_name"], phone=request.POST["phone"], email=request.POST["email"])
#return render(request, "core/home.html")
return HttpResponseRedirect('/')
#return render("core/home.html", context)
#else:
# Assistant.objects.create(UserManegement=request.POST["user"], Event=request.POST["event"])
# return render( "core/home.html")
else:
event_form = EventForm()
return render(request, 'core/home.html', {'form': event_form})
The response what shows me the server:
[24/Feb/2021 10:27:05] "GET / HTTP/1.1" 200 9404
Hola
Use Model Form instead of form.Forms
class EventForm(forms.ModelForm):
class Meta:
model = In which You want to save data
fields = "__all__" If you want to select all fields from your model or you can specify the list of fields in a list or tuple
fields = ("field1","Field2","field3")
This form will automatically map all your Model Field to HTML
and just render this form in HTML.In View also you dont need to write so much code
def attend_to(request):
event_form = EventForm()
if request.method == 'POST':
event_form = EventForm(request.POST)
if event_form.is_valid():
event_form.save()
return redirect()#After Form submission use redirect.Never use render as it can create duplicate enteries on refresh.
context = {"form":event_form}#Passing the form in HTML
return render( "core/home.html",context)
HTML
{% csrf_token %}
<div class="form-group">
<label for="first_name">Nombre:</label>
{{form.fieldname}}
<div class="input-group">
{{form.first_name}}
</div>
</div>
<div class="form-group">
<label for="last_name">Apellidos:</label>
<!--<input id="last_name" name="last_name" placeholder="Apellidos del participante" type="text" required="required" class="form-control">-->
<div class="input-group">
{{form.last_name}}
</div>
</div>
<div class="form-group">
<label for="phone">Teléfono:</label>
<!--<input id="phone" name="phone" placeholder="Teléfono del participante" type="text" required="required" class="form-control">-->
<div class="input-group">
{{form.phone}}
</div>
</div>
<div class="form-group">
<label for="email">Correo electrónico:</label>
<!--<input id="email" name="email" placeholder="Correo electrónico del participante" type="text" required="required" class="form-control">-->
<div class="input-group">
{{form.email}}
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary btn-block py-2" value="Enviar">
</div>
</form>
You can use load_widget_tweaks to style your form instead of writing code in your form
Add the blank form in the register_event view function.
def register_event(request, event_id):
event_form = EventForm()
event = get_object_or_404(Event, id=event_id)
return render(request, "events/event_register.html", {'event':event, 'form': event_form})
This will ensure the form fields are displayed in your event_register.html view that you can then submit.
Then in your form html, change the action attribute to submit the form data to the attend_to view function.
From this
<form action="" method="POST">
to this
<form action="{% url 'attend_to' %}" method="POST">

Issue in form validation

I want to validate my update form using form validation. When i leave a field blank and hit update button I get a blank page showing the error message. I want that error message to be displayed on top of that particular field when I leave it blank and hit update button.
This is my latest update view:
def update(request, id):
item = get_object_or_404(BookEntry, id=id)
if request.method == "POST":
form = UpdateForm(request.POST, instance=item)
# print template
error_messages = {
'error': form.errors,
}
if form.is_valid():
print(form.cleaned_data)
post = form.save(commit=False)
post.save()
return HttpResponseRedirect(reverse('bms:index'), id)
else:
form = UpdateForm()
return HttpResponse(json.dumps(error_messages))
return render(request, 'index.html',{'form':form})
This is my old update view:
def update(request, id):
item = get_object_or_404(BookEntry, id=id)
if request.method=="POST":
form = UpdateForm(request.POST, instance=item)
if form.is_valid():
post=form.save(commit=False)
post.save()
return HttpResponseRedirect(reverse('bms:index'), id)
else:
form=UpdateForm(instance=item)
return HttpResponseRedirect(reverse('bms:index'), id)
return render(request, 'bms.html',{'form':form})
This is my forms.py:
class UpdateForm(forms.ModelForm):
title = forms.CharField(max_length=100)
author = forms.CharField(max_length=100)
edition = forms.CharField(max_length=100)
publisher = forms.CharField(max_length=100)
genre = forms.CharField(max_length=100)
detail = forms.CharField(max_length=100)
language = forms.CharField(max_length=100)
price = forms.IntegerField()
dop = forms.CharField(max_length=100)
cop = forms.CharField(max_length=100)
copyright = forms.CharField(max_length=100)
isbn = forms.IntegerField()
class Meta:
model = BookEntry
fields = '__all__'
This is my html form:
<form action="{% url 'bms:update' book.id %}" id="updateform" name="updateform" method="POST">
{% csrf_token%}
<div class = "form-group">
<label for = "title">
Title:
</label>
<input class = "form-control" id="book_title" type = "text" name="title" value="{{ book.title }}">
</div>
<div class="form-group">
<label for = "author">
Author:
</label>
<input id="book_author" class = 'form-control' type = "text" name="author" value="{{ book.author }}">
</div>
<div class = "form-group">
<label for = "edition">
Edition:
</label>
<input id="book_edition" type = "text" class = 'form-control' name="edition" value="{{ book.edition }}">
</div>
<div class = "form-group">
<label for ="publisher">
Publisher:
</label>
<input id="book_publisher" type = "text" name="publisher" class = 'form-control' value="{{ book.publisher }}"/>
</div>
<div class = "form-group">
<label for ="genre">
Genre:
</label>
<input id="book_genre" type = "text" name="genre" class = 'form-control' value="{{ book.genre }}"/>
</div>
<div class = "form-group">
<label for ="detail">
Detail:
</label>
<input id="book_detail" type = "text" name="detail" class = 'form-control' value="{{ book.detail }}"/>
</div>
<div class = "form-group">
<label for ="language">
Language:
</label>
<input id="book_language" type = "text" name="language" class = 'form-control' value="{{ book.language }}"/>
</div>
<div class = "form-group">
<label for ="price">
Price:
</label>
<input id="book_price" type = "text" name="price" class = 'form-control' value="{{ book.price }}"/>
</div>
<div class = "form-group">
<label for ="dop">
DOP:
</label>
<input id="book_dop" type = "text" name="dop" class = 'form-control' value="{{ book.dop }}"/>
</div>
<div class = "form-group">
<label for ="cop">
COP:
</label>
<input id="book_cop" type = "text" name="cop" class = 'form-control' value="{{ book.cop }}"/>
</div>
<div class = "form-group">
<label for ="cop">
Copyright
</label>
<input id="book_copyright" type = "text" name="copyright" class = 'form-control' value="{{ book.copyright }}"/>
</div>
<div class = "form-group">
<label for ="isbn">
ISBN:
</label>
<input id="book_isbn" type = "text" name="isbn" class = 'form-control' value="{{ book.isbn }}"/>
</div>
<input type = "submit" value="Update" id="update" class = "btn btn-success" style="font-size:18px;" />
</form>
This is the URL it shows when a field is left empty:
http://127.0.0.1:8000/bms/update/2/
And this is the error message:
{"error": {"edition": ["This field is required."]}}
I had left edition field empty to check if validation is working properly or not.
Can anyone suggest me how to do it the right way?
As Daniel pointed out, you need to re-render the form.
The basics of HTTP Form Post are:
If the form is valid: save + do a HttpResponseRedirect
If the form is not valid; re-render the same template with the errors
Change your function to:
def update(request, id):
item = get_object_or_404(BookEntry, id=id)
if request.method == "POST":
form = UpdateForm(request.POST, instance=item)
# print template
error_messages = {
'error': form.errors,
}
if form.is_valid():
print(form.cleaned_data)
post = form.save(commit=False)
post.save()
return HttpResponseRedirect(reverse('bms:index'), id)
return render(request, 'index.html',{'form':form}) # Form invalid case is handled here; the form is reused from above; form.errors is available in the template now
else:
pass # Handle GET requests here

I wanna set minlength&maxlength in template of input tag

I wrote in index.html
<div class="heading col-lg-6 col-md-12">
<h2>New account registration</h2>
<form class="form-horizontal" action="regist_save/" method="POST">
<div class="form-group-lg">
<label for="id_username">username</label>

 {{ regist_form.username }}
</div>
 
<div class="form-group-lg">
<label for="id_email">email</label>

 {{ regist_form.email }}
</div>
<div class="form-group-lg">
<label for="id_password">password</label>
{{ regist_form.password1 }}
</div>
 
<div class="form-group-lg">
<label for="id_password">password(conformation)</label>
{{ regist_form.password2 }}
<p class="help-block">{{ regist_form.password2.help_text }}</p>
</div>
 
<div class="form-group-lg">
<div class="col-xs-offset-2">
<button type="submit" class="btn btn-primary btn-lg">SUBMIT</button>
<input name="next" type="hidden"/>
</div>
</div>
{% csrf_token %}
</form>
</div>
I wanna set minlength&maxlength in template of username&password input tag.If i wrote in html stye,it is
<form class="form-horizontal" action="regist_save/" method="POST">
<div class="form-group-lg">
<label for="id_username">username</label>

 <input id="id_username" name="username" type="text" value="" minlength="5" maxlength="12" placeholder="username" class="form-control">
</div>
 
<div class="form-group-lg">
<label for="id_email">email</label>

 {{ regist_form.email }}
</div>
<div class="form-group-lg">
<label for="id_password">password</label>
<input id="id_password1" name="password1" type="password1" value="" minlength="8" maxlength="12" placeholder="password1" class="form-control">
</div>
 
<div class="form-group-lg">
<label for="id_password">password(conformation)</label>
<input id="id_password2" name="password2" type="password2" value="" minlength="8" maxlength="12" placeholder="password2" class="form-control">
<p class="help-block">{{ regist_form.password2.help_text }}</p>
</div>
 
<div class="form-group-lg">
<div class="col-xs-offset-2">
<button type="submit" class="btn btn-primary btn-lg">SUBMIT</button>
<input name="next" type="hidden"/>
</div>
</div>
{% csrf_token %}
</form>
in forms.py
class RegisterForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email','password1','password1',)
def __init__(self, *args, **kwargs):
super(RegisterForm, self).__init__(*args, **kwargs)
self.fields['username'].widget.attrs['class'] = 'form-control'
self.fields['email'].widget.attrs['class'] = 'form-control'
self.fields['password1'].widget.attrs['class'] = 'form-control'
self.fields['password2'].widget.attrs['class'] = 'form-control'
in views.py
#require_POST
def regist_save(request):
regist_form = RegisterForm(request.POST)
if regist_form.is_valid():
user = regist_form.save(commit=False)
password = regist_form.cleaned_data.get('password')
user.set_password(password)
user.save()
login(request, user)
context = {
'user': request.user,
}
return redirect('detail')
context = {
'regist_form': regist_form,
}
return render(request, 'registration/regist.html', context)
I wanna set username minlength="5" &maxlength="12" and password minlength="8" & maxlength="12".I wanna write it in template,although I searched the way in Google but i cannot find it.I think i can do it by template but do i misunderstand it?Can't i do it in template?
you can set maxlength and minlength by using these attributes with your desired limit and validation will work accordingly
Working example on W3schools

I have a bound ModelForm that is invalid

I am trying to create a ModelForm that links to an external database, and when you submit the form the external database gets updated. The problem comes when I check the validity of the form, it is invalid.
I have done some researching into this and found the most common problem was that the form is not bound, but when I use print(form.non_field_errors) I get:
<bound method BaseForm.non_field_errors of <EmailForm bound=True, valid=False, fields=(subject;body;name;altsubject;utm_source;utm_content;utm_campaign)>
models.py:
class MarketingEmails(models.Model):
messageid = models.AutoField(db_column='column1', primary_key=True)
subject = models.CharField(db_column='column2', max_length=2000)
body = models.TextField(db_column='column3') #using a text field as there is no maximum length
name = models.CharField(db_column='column4', max_length=25)
altsubject = models.CharField(db_column='column5', max_length=2000)
utm_source = models.CharField(db_column='column6', max_length=25)
utm_content = models.CharField(db_column='column7', max_length=25)
utm_campaign = models.CharField(db_column='column8', max_length=25)
class Meta:
managed = False
db_table = ''
forms.py:
class EmailForm(forms.ModelForm):
class Meta:
model = MarketingEmails
fields = ['messageid','subject','body','name','altsubject','utm_source','utm_content','utm_campaign']
views.py:
def emailinfo(request, pk):
if request.session.has_key('shortname'):
shortname = request.session['shortname']
rows = get_object_or_404(MarketingEmails, pk=pk)
if request.method == 'POST':
form = EmailForm(request.POST)
print(form.errors)
print(form.non_field_errors)
if form.is_valid():
form.save()
print("form is valid")
return redirect('marketingemails:emailinfo', pk = rows.messageid)
return render(request, 'marketingemails/emailinfo.html',{'shortname': shortname, 'rows': rows})
else:
return HttpResponseRedirect(reverse('common:login'))
urls.py:
app_name = 'marketingemails'
urlpatterns = [
url(r'^marketing/emails/(?P<pk>[0-9]+)/$', marketingviews.emailinfo, name='emailinfo'),
]
html:
<form method="POST" class="post-form" action ="">
{% csrf_token %}
<label for="exampleTextarea">Name</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.name }}</textarea>
<label for="exampleTextarea">Subject</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.subject }}</textarea>
<label for="exampleTextarea">Alternative Subject</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.altsubject }}</textarea>
<label for="exampleTextarea">Body</label>
<div class="ibox-content no-padding">
<div class="summernote">
{{ rows.body }}
</div>
</div>
<label for="exampleTextarea">utm_source</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.utm_source }}</textarea>
<label for="exampleTextarea">utm_content</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.utm_content }}</textarea>
<label for="exampleTextarea">utm_campaign</label>
<textarea class="form-control" id="exampleTextarea" rows="1">{{ rows.utm_campaign }}</textarea>
<button type="submit" class="save btn btn-default">Save</button>
</form>
Your HTML form doesn't name the fields so the form can't get them. You want to use the form for rendering too : https://docs.djangoproject.com/en/1.11/topics/forms/#working-with-form-templates

django forms, not valid

so no matter what I seem to do I can't get a valid form from just a integer field.
Controller:
def upload_image(request):
if request.method == "POST":
form = AddFloorplan(request.POST, request.FILES)
print request.POST.get('floornumber')
if form.is_valid():
print 'valid'
else:
print(form.errors)
return redirect("/wayfinder/editor/")
Form:
class AddFloorplan(forms.Form):
floor_number = forms.IntegerField(required=True)
Template:
<form action="/wayfinder/addfloorplan/" method="POST" enctype="multipart/form-data"> {% csrf_token %}
<div class="input-field col s12">
<input id="floornumber" autofocus name="floornumber" placeholder="Floor Number" type="text" required>
</div>
<div class="col s12">
<p>
<button class="btn waves-effect waves-light z-depth-0" type="submit" name="action">
<span>Upload</span>
</button>
</p>
</div>
</form>
had no luck passing the values
The name of your form field, floor_number
floor_number = forms.IntegerField(required=True)
does not match the name of your form input, floornumber
<input id="floornumber" autofocus name="floornumber" placeholder="Floor Number" type="text" required>
You need to use the same name in both places.

Categories