So I'm stuck on why validation errors aren't showing for this particular form. They are showing up fine on all my other forms, but not this one.
I can empirically see the validation at work because when office_street_address is none, the form is not saving. But the form.non_field_error doesn't seem to have any errors.
forms
class PremiumAgentForm(forms.ModelForm):
class Meta:
model = Agent
exclude = ['field1', 'field2', ...]
def __init__(self, *args, **kwargs):
super(PremiumAgentForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
visible.field.widget.attrs['class'] = 'form-control'
def clean(self):
cd = super(PremiumAgentForm, self).clean()
a = cd.get('office_street_address')
if a == None:
raise forms.ValidationError("Error")
return cd
html
<form class="row justify-content-center" enctype="multipart/form-data" method="post">
{% csrf_token %}
{% for error in form.non_field_errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
{% if form.non_field_errors %}
<p style="color: red">there are errors</p>
{% else %}
<p>no errors</p> # This is always displayed.
{% endif %}
<div class="col-sm-4">
{% for field in form %}
<div class="form-group pb-3">
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
{{ field.label_tag }}
{{ field }}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text|safe }}</small>
{% endif %}
</div>
{% endfor %}
<button class="button2"><span>Submit</span></button>
</div>
</form>
views.py
def edit_profile(request):
if request.method == 'POST':
form = PremiumAgentForm(request.POST, request.FILES, instance=agent)
if form.is_valid():
form.save()
return HttpResponseRedirect(request.META['HTTP_REFERER'])
else:
agent = get_object_or_404(Agent, pk=request.user.agent.pk)
form = PremiumAgentForm(instance=agent)
return render(request, 'edit_profile.html', {'form': form})
In your case, you keep the form if it is valid, and after that you do a redirect, even if the form is not valid. This should help:
if not form.is_valid():
return render(request, 'edit_profile.html', {'form': form})
form.save()
Related
I have got an error when I tried to display a form in function-based view in Django. I could display it in another HTML file and users can make their comments to the blog. But, I think it can be more convenient for users if they can make a comment on the same blog-detail HTML file, so I wanna implement it.
When I tried, this error showed up. "NoReverseMatch at /blogs/blog/30/
Reverse for 'blog' with no arguments not found. 1 pattern(s) tried: ['blogs/blog/(?P[0-9]+)/$']"
Any comments can help me and thanks for your time in advance!!
Here are the codes I wrote...
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('user', 'text',)
#views.py
#login_required
def blog(request, pk):
blog = get_object_or_404(Blog, pk=pk)
form = CommentForm()
# if request.method == 'POST':
# form = CommentForm(request.POST)
# if form.is_valid():
# comment = form.save(commit=False)
# comment.blog = blog
# comment.save()
# return redirect('blog', pk=blog.pk)
# else:
# form = CommentForm()
if blog.link_1 is not None and blog.link_2 is not None:
link_1 = blog.link_1
link_2 = blog.link_2
context = {
'blog': blog,
'link_1': link_1,
'link_2': link_2,
'form': form,
}
elif blog.link_1 is not None or blog.link_2 is not None:
link_1 = blog.link_1
link_2 = blog.link_2
context = {
'blog': blog,
'link_1': link_1,
'link_2': link_2,
'form': form,
}
else:
context = {
'blog': blog,
'form': form,
}
return render(request, 'blog/blog.html', context)
#login_required
def add_comment(request, pk):
blog = get_object_or_404(Blog, pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.blog = blog
comment.save()
return redirect('blog', pk=blog.pk)
else:
form = CommentForm()
context = {
'form': form,
}
return render(request, 'blog/blog.html', context)
#urls.py
path('blog/<int:pk>/', views.blog, name='blog'),
path('blog/<int:pk>/comment/', views.add_comment, name='add_comment'),
#blog.html
{% extends 'base.html' %}
{% block title %}|{{ blog.title }}{% endblock %}
{% block content %}
<div class="header-bar">
← 戻る
</div>
<div class="body-container">
<div class="created-edit-delete">
<p>
{% if request.user == blog.user %}
あなたが{{ blog.created }}に作成</p>
{% else %}
{{ blog.user }}が{{ blog.created }}に作成</p>
{% endif %}
<div class="icons">
{% if request.user == blog.user %}
{% endif %}
</div>
</div>
<h1>{{ blog.title }}</h1>
<p class="blog-content">{{ blog.content_1 }}</p>
{% if blog.content_2 %}
<p class="blog-content">{{ blog.content_2 }}</p>
{% endif %}
{% if blog.content_2 %}
<p class="blog-content">{{ blog.content_3 }}</p>
{% endif %}
<div class="ref-links">
{% if link_1 %}
参考リンク
{% endif %}
{% if link_2 %}
参考リンク
{% endif %}
</div>
<hr>
<div class="comment-area">
<div class="comment-form">
<h2>New comment</h2>
<form action="{% url 'add_comment' blog.id %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="button">追加</button>
</form>
</div>
<div class="comment-all">
{% for comment in blog.comments.all %}
<div class="comment">
<div class="date">{{ comment.created }}</div>
<strong>{{ comment.user }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
You have called blog URL here ← 戻る and forgot to pass id inside your URL that's why it's showing this error
NoReverseMatch at /blogs/blog/30/ Reverse for 'blog' with no arguments not found. 1 pattern(s) tried: ['blogs/blog/(?P[0-9]+)/$']
you have to pass id here like this
← 戻る
here with this code the form errors are not displaying properly.The all error messages says, this field is required only.how can i define my custom form.error message in the template.
template
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<p> {{ error }} </p>
{% endfor %}
{% endfor %}
{% endif %}
<div class="form-group">
<h5>Full Name <span class="text-danger">*</span></h5>
<div class="controls">
<input type="text" name="name" class="form-control" title="Full Name is required" > </div>
</div>
<div class="form-group">
<h5>Courses<span class="text-danger">*</span></h5>
<div class="controls">
{% for course in courses %}
<input name ="courses" type="checkbox" id="course-{{course.id}}" value="{{course.id}}" autofocus title="Please Check at least one course">
<label for="course-{{course.id}}">{{course.title}}</label>
{% endfor %}
</div>
</div>
views.py
if request.method == 'POST':
form = AddStudentForm(request.POST, request.FILES)
if form.is_valid():
student = form.save(commit=True)
student.save()
messages.success(request, 'student with name {} added.'.format(student.name))
return redirect('admin:add_student')
else:
form = AddStudentForm()
return render(request, 'admin/add_student.html', {'form': form})
in your views.py pass the form with errors like this
if request.method == 'POST':
form = AddStudentForm(request.POST, request.FILES)
if form.is_valid():
student = form.save(commit=True)
student.save()
messages.success(request, 'student with name {} added.'.format(student.name))
return redirect('admin:add_student')
return render(request, 'admin/add_student.html', {'form': form})
else:
form = AddStudentForm()
return render(request, 'admin/add_student.html', {'form': form})
That means you should remove the else part
and in your template code
{% if form.errors %}
<div class="alert alert-danger">
{{ form.errors }}
</div>
{% endif %}
Updated the answer to get proper answer when you load the view first time
The form submits but immediately says this field is required... although it was filled out. What am I doing wrong
In my view:
def fileupload(request):
if request.user.is_authenticated and request.user.is_staff:
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES.getlist('file_field'))
return HttpResponseRedirect('/fileupload/')
else:
form = UploadFileForm()
return render(request, 'fileupload.j2.html', {'form': form})
return HttpResponseForbidden('<h1>403 Forbidden</h1>')
with this form:
class UploadFileForm(forms.Form):
kit_number = forms.CharField(label="Kit number", max_length=100, required=True, help_text='Required.')
file_field = forms.FileField(label='Upload kit result')
and template:
{% extends "menu.j2.html" %}
{% block content %}
{% if request.user.is_authenticated and request.user.is_staff %}
<h3>File upload</h3><br><br>
<form action="/fileupload/" method="post">
{% csrf_token %}
<div class="form-group">
<table>
{{ form.as_table() }}
</table>
</div>
<input id="button" class="btn" type="submit" value="Sent">
</form>
{% else %}
You are not authorized to see this page
{% endif %}
{% endblock %}
You forgot to set the form enctype.
<form action="/fileupload/" method="post" enctype="multipart/form-data">
I have a custom user model
class User(AbstractUser):
company = models.CharField(max_length=30, blank=True)
When I try to change my password using the ChangePasswordForm, upon submit, nothing happens.
#login_required
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(data=request.POST, user=request.user)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
return redirect('/account/profile')
else:
form = PasswordChangeForm(request.user)
args = {'form': form}
return render(request, 'accounts/change_password.html', args)
change_password.html
{% extends 'base.html' %}
{% block head %}
{% endblock %}
{% load crispy_forms_tags %}
{% crispy form form.helper %}
{% block body %}
<div class="container-fluid">
<div class="card">
<div class="card-body">
<h3>Change password</h3><br>
<form method="post">
{% csrf_token %}
{% crispy form %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
{%endblock%}
This was working before with a regular usermodel
hope someone can help.
So I have my view:
def home_page(request):
form = UsersForm()
if request.method == "POST":
form = UsersForm(request.POST)
if form.is_valid():
form.save()
c = {}
c.update(csrf(request))
c.update({'form':form})
return render_to_response('home_page.html', c)
my forms.py:
class UsersForm(forms.ModelForm):
class Meta:
model = Users
widgets = {'password':forms.PasswordInput()}
def __init__(self, *args, **kwargs):
super( UsersForm, self ).__init__(*args, **kwargs)
self.fields[ 'first_name' ].widget.attrs[ 'placeholder' ]="First Name"
self.fields[ 'last_name' ].widget.attrs[ 'placeholder' ]="Last Name"
self.fields[ 'password' ].widget.attrs[ 'placeholder' ]="Password"
and my template:
<html>
<body>
<form method="post" action="">{% csrf_token %}
{{ form.first_name }} {{form.last_name }} <br>
{{ form.password }} <br>
<input type="submit" value="Submit Form"/>
</form>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<p> {{ errors }} </p>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<p> {{ error }} </p>
{% endfor %}
{% endif %}
</body>
</html>
Now, keep in mind that before I split the form field, my form just looked like this:
<form method="post" action="">{% csrf_token %}
{{ form }}
<input type="submit" value="Submit Form"/>
</form>
and if the form had a problem (like if one of the fields was missing) it would automatically give an error message. After I split up the form fields in the template (made {{ form.first_name }}, {{ form.last_name }} and {{ form.password }} their own section) it stopped automatically giving error messages. Is this normal?
But the main problem is, how come my {{ if form.errors }} statement is not working / displaying error messages if there are error messages? For example, if I purposely not fill out a field in the form and I click submit, the database does not get updates (which is a good thing) but it does not give any error messages. Any idea why?
I also tried remove the {{ forms.non_field_errors }} and tried to return just field errors like so:
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<p> {{ errors }} </p>
{% endfor %}
{% endfor %}
{% endif %}
but it still doesn't work.
I found the mistake (typo).
The snippet should be:
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<p> {{ error }} </p>
{% endfor %}
{% endfor %}
{% endif %}
I had errors instead of error.
you have to send your form context again if is_valid() isn't true,
if form.is_valid():
return redirect('/user/contact/')
else:
return render(request, 'users/contact.html', context={'form': form})
because your errors will display in your form
else: it will return ValueError
Add this snippets in views.py like this
if request.method == "POST":
fm = UserRegsitrationForm(request.POST)
if fm.is_valid():
fm.save()
else:
fm = UserRegsitrationForm()
context = {'fm':fm}
return render(request,'registration.html',context)
The error capture could very well have been done with:
{% for field in form %}
{{ field.errors }}
{% endfor %}