Good afternoon Community,
I hope you are all well.
I am building my first website and I have the following problem; when I try to create a new user, if the user enters the wrong data the template does not show the error. Any hints?
Template:
<form action= "" method='post'>
{% csrf_token %}
{% for field in form %}
<p>{{field.label}}{{field}}</p>
{% endfor %}
<button type="submit" class="btn btn-success">Create User</button>
Views.py:
def register_page(request):
form = UserForm
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('http://127.0.0.1:8000/login_user/')
context = {'form' : form}
return render(request, 'simple_investing/register.htm', context)
Forms.py:
class UserForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
As is discussed in the rendering fields manually section of the documentation, for the fields you should also render {{ field.errors }}, and the {{ form.non_field_errors }} which deals with errors not specific to one form.
The template thus should look like:
<form action= "" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
<p>
{{ field.errors }}
{{ field.label }}
{{ field }}
</p>
{% endfor %}
<button type="submit" class="btn btn-success">Create User</button>
</form>
The section also discusses how to enumerate over the errors, and apply certain styling to these errors.
Related
Some troubles with validation.
I'm using this construction in my template:
<form method="POST">
{% csrf_token %}
{{ formset.media.js }}
{% for form in formset %}
<p>{{ form }}</p>
{% endfor %}
<button type="submit" class="btn btn-primary">Send</button>
And this validation in views:
def flow_type(request):
patternFormset = modelformset_factory(CashFlowPattern, fields='__all__')
if request.method == 'POST':
formset = patternFormset(request.POST)
if formset.is_valid():
formset.save()
formset = patternFormset()
template = 'cash_table/index.html'
context = {
# 'form': form,
'formset': formset
}
return render(request, template, context)
I get form at page but nothing happens after submit.
But if I use another template construction it works:
<form method="POST">
{% csrf_token %}
{{ formset.media.js }}
{{ formset }}
<button type="submit" class="btn btn-primary">Send</button>
</form>
But then I get all fields of new form at the same line.
I think you need to have {{ formset.management_form }} in the template where you iterate through the forms of the formset so that Django knows that it is a formset, and knows how many forms are in the formset, etc...
<form method="POST">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.media.js }}
{% for form in formset %}
<p>{{ form }}</p>
{% endfor %}
<button type="submit" class="btn btn-primary">Send</button>
When you use {{ formset }} the management is done automatically (it's a shortcut).
Source: https://docs.djangoproject.com/en/4.1/topics/forms/formsets/#custom-formset-validation
New to Django and I am attempting to create a customer registration form and was successful. However the tutorial I followed showed me how to iterate through a loop, the contents of my registration_form which doesn't really give me much flexibility from a UI perspective, or so it seems. Can someone tell me how to customize this form based on the code I've got?
HTML:
<h1>This is the register.html</h1>
<div class="col-md-4 offset-md-4">
<form method="post">
{% csrf_token %}
{% for field in registration_form %}
<p>
{{field.label_tag}}
{{field}}
{% if field.help_text %}
<small style="color: grey;">{{field.help_text}}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: grey;">{{error}}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit">Register</button>
</form>
</div>
views.py
def registration_view(request):
context = {}
if request.POST:
form = RegistrationForm(request.POST)
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)
login(request, account)
return redirect('home')
else:
context['registration_form'] = form
else:
form = RegistrationForm()
context['registration_form'] = form
print(context)
return render(request, 'accounts/register.html', context)
forms.py
class RegistrationForm(UserCreationForm):
email = forms.EmailField(max_length=100, help_text='Required. Add a valid email address')
class Meta:
model = Account
fields = ('email', 'username', 'password1', 'password2', 'first_name', 'last_name')
the form renders and works fine with registration, just looks kinda crappy. thanks!
You could render each field individually and take advantage of bootstrap styling as well. For example for the email field, you could have something like below
<div class="form-group">
{{ registration_form.email.label_tag }}
{{ registration_form.email }}
</div>
You can also have a div below it to display its errors on post
<div class="errors">
{% if registration_form.email.errors %}
{% for error in registration_form.email.errors %}
<strong>{{ error|escape }}</strong>
{% endfor %}
{% endif %}
</div>
I'm making an app that has basic crud functionalities.
A parent model is extended by a child model through a foreign key relationship. The second model ads images to the first. I've got the basic crud working ie. adding images and relating them to the first model. I have a hard time getting the child model's form to show images that has already been added through making use of an instance. I would like if possible keep the create and update view in a single view function.
I've tried variations of the reverse lookup _set method, but I'm just getting other confusing errors. This is the one that makes most sense to me.
def add_image(request):
if 'product_id' in request.GET:
product_id = request.GET['product_id']
product = get_object_or_404(Product, id=product_id)
if request.method == 'POST':
form = ProductImageForm(request.POST, request.FILES)
if form.is_valid():
productimage = form.save(commit=False)
productimage.product = product
productimage.save()
return redirect('dashboard:products')
else:
print(form.errors)
else:
if product.productimage_set:
i = product.productimage_set.all()
form = ProductImageForm(instance=i)
else:
form = ProductImageForm()
return render(request, 'dashboard/add_image.html', {'form': form})
class ProductImageForm(forms.ModelForm):
class Meta:
model = ProductImage
exclude = ['product']
<form method="post" action="" class="width-100" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.label_tag }}
{% render_field field class="form-control"%}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
<br>
<input class="btn btn-primary btn-rounded btn-block" type="submit" value="Add Images"/>
<a class="btn btn-light btn-block btn-rounded" href="{% url 'dashboard:products' %}">Cancel</a>
</form>
I would like the form to show the already added images from the instance I'm calling, should the user want to edit the model instance. Instead, I'm getting an error:
AttributeError at /dashboard/products/add-image/
'QuerySet' object has no attribute '_meta'
I try to use Django forms but I have problems displaying all the fields on my Template.
I have created a form in the form.py file as:
class UploadCSVForm(forms.Form):
title = forms.CharField(max_length=255, help_text="Please type here", required=True)
csv_load = forms.FileField()
In my corresponding view I import the form as:
from myproject.myapp.forms import UploadCSVForm
and then in the specific view function I render the form as;
if request.method == 'GET':
....
....
form = UploadCSVForm()
ctx['form'] = form
return render_to_response(template, RequestContext(request, ctx))
Last in my template I call the form as:
<form id="file-uploader" method="post" enctype="multipart/form-data" action="{% url "layer" %}">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<button type="submit" id="upload-button" class="btn btn-danger">Upload</button>
</form>
I only get to see the csv_load but not the title.
What am I doing wrong here?
When I enter an invalid email adress I cant see an error message like "This is not an invalid email".
My comment_form.html:
{% load i18n %}
<form action="/comment/create/" method="post">
{% csrf_token %}
{{ form.errors }}
{% for field in form %}
<div class="fieldWrapper">
{{ field.label_tag }}
{{ field }}<p>
</div>
{% endfor %}
<input type="hidden" name = "object_id" value="{{object_id}}" />
<input type="hidden" name= "next" value="{{ next }}" />
<input type="submit" value="{% trans "Submit" %}">
</form>
my post_detail.html:
extends "base.html" %}
{% block content %}
<div id="exap">
{{ post.content }}
</div>
<div class="comment">
{% for comment in comments %}
<user>{{ comment.owner }}</user>
{{ comment.content}}
{% endfor %}
</div>
{% include "comment_form.html" %}
{% endblock %}
this is my comment.views
def create(request):
if request.method == 'POST':
form = CommentForm(request.POST)
email = request.POST.get('email')
next = request.POST.get('next')
if form.is_valid():
content_type = ContentType.objects.get(app_label="post", model="post")
object_id = request.POST["object_id"]
comment = Comment.objects.create(
content_type = content_type,
object_id = object_id,
content = request.POST.get('content'),
owner= request.POST.get('owner'),
email = request.POST.get('email')
)
else:
print form.errors
else:
form = CommentForm()
return HttpResponseRedirect(next)
Error message doesnt display in template ?
Where am I wrong ?
karthikr is trying to tell you what is wrong in the comments. You are not using the form to validate, so it won't show any errors. Instead of doing if validateEmail(email) you should have the email validation code inside the form class, and in the view you call if form.is_valid().
Plus, when you do write the form's clean_email method, you should not be catching ValidationError: that's the way that errors are passed on to the form's errors list.