I want to show custom error messages, if some field is not valid. I have following model:
class Test(models.Model):
name = models.IntegerField(max_length=10)
class TestForm(forms.ModelForm):
class Meta:
model = Test
fields = '__all__'
error_messages = {
'name': {
'max_length': ("This user's name is too long."),
},
}
The view is:
def test(request):
if request.method == 'POST':
print "The form is submitted successfully."
form = TestForm(request.POST)
if form.is_valid():
print request.POST.get("name")
return render(request, 'test.html',{'form' : TestForm()})
else:
print "Something wrong with inputs."
return render(request, 'test.html',{'form' : form})
else:
return render(request,'test.html',{'form' : TestForm()})
and template is:
{% extends "base.html" %}
{% block title %}
Test Form
{% endblock title %}
{% load widget_tweaks %}
{% block body_block %}
<h1>hello from test</h1>
<form class='form-horizontal' role='form' action="." method="POST">
<div class='form-group'>
<label class='control-label col-md-2 col-md-offset-2' for='id_name'>Name</label>
<div class='col-md-6'>
{% render_field form.name class="form-control" placeholder="Full Name" type="text" %}
{{ form.name.error_messages }}
{# I want to add here classes for alert-error etc #}
</div>
</div>
{% csrf_token %}
<div class='form-group'>
<div class='col-md-offset-4 col-md-6'>
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
{% endblock body_block %}
But, I am not getting any messages in the template. Please help me to solve this.
Change form.name.error_messages to form.name.errors in your template.
It seems you render fields/errors one by one manually, explained here:
You may want to consider a more automatic approach using a {% for %} template tag.
EDIT: To change the default error message, you need to update your error_messages in the form Meta and overwrite the key used by django, in this case it is key invalid, based on IntegerField source:
class Meta:
model = Test
fields = '__all__'
error_messages = {
'some_integer_field': {
'invalid': 'some custom invalid message',
},
}
Related
I have this app and its working but i'm confused whether to use form method or POST.get method. with form i'm getting so many challenges like rendering form on custom html
suppose i have this change password screen, for that i need to create form then use this on html template and with custom html it gets more complicated to use form fields.
forms.py:
class ChangePasswordForm(PasswordChangeForm):
old_password = forms.CharField(label="Old Password", strip=False, widget=forms.PasswordInput(
attrs={'class': 'formField password-genrInput'}))
new_password1 = forms.CharField(label="New Password", strip=False, widget=forms.PasswordInput(
attrs={'class': 'formField password-genrInput'}))
new_password2 = forms.CharField(label="Confirm Password", strip=False, widget=forms.PasswordInput(
attrs={'class': 'formField password-genrInput'}))
class Meta:
model = User
fields = ('old_password', 'new_password1', 'new_password2')
views.py:
# Password Change View
def changePassword(request):
if request.method == 'POST':
form = ChangePasswordForm(request.user, request.POST)
print(form)
if form.is_valid():
print("form valid")
user = form.save()
update_session_auth_hash(request, user)
messages.success(request, "Password Changed Successfully")
return redirect('changePassword')
else:
messages.error(request, "Something Went Wrong, Please Try Again ")
return redirect('changePassword')
else:
form = ChangePasswordForm(request.user)
return render(request, 'admin/user_auth/change_password.html', {
'form': form
})
html:
{% extends "admin/layouts/default.html" %}
{% load static %}
{% block content%}
<div class="row">
<div class="col">
<div class="titleBlock">
<h1><i class="fas fa-chevron-circle-left mr-3"></i>Back</h1>
</div>
<div class="card">
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li {% if message.tags %} class=" {{ message.tags }} " {% endif %}> {{ message }} </li>
{% endfor %}
</ul>
{% endif %}
<form method="post">
{% csrf_token %}
<div class="formBlock">
<div class="row password-genr mt-5">
{% for field in form %}
<div class="col-md-7">
<div class="formControl static ">
<label for="" class="formLabel">{{field.label}}</label>
{{field}}
</div>
</div>
{%endfor%}
<div class="col-md-7">
<div class="btnBlock mt-5">
<button type="submit" class="btn btn-md">Save</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{%endblock content%}
but with simple method i would have checked first if new password and confirm password are matching then
old_password = request.POST.get('old_password')
new_password = request.POST.get('new_password')
check the old password are matching with db then save the new password on db.
so which method should i use and why?
TO do This you can do something like this.
from django.contrib.auth.hashers import check_password
current_password = request.user.password
old_password = request.POST.get('old_password')
matchcheck= check_password(old_password, current_password) #this returns True or False
if matchcheck:
#change your password
else:
#tell the user the password is wrong.
The method above is useful by example if a user wants to delete his account to do so you can use the idea to check whether he knows his password or not ,if he knows it then he can delete his account.
And if you do not want to implement it by yourself you can use the built-in in Django(i really recommend this method for changing password because it well done and less headache).
How are you?
I m totally new in Django.I designed a page and I wanted to show a django form(edit or create) in a well designed HTML page. but i do not know how.
This is my owner method:
class OwnerUpdateView(LoginRequiredMixin, UpdateView):
"""
queryset to the requesting user.
"""
def get_queryset(self):
print('update get_queryset called')
""" Limit a User to only modifying their own data. """
qs = super(OwnerUpdateView, self).get_queryset()
return qs.filter(user=self.request.user)
class OwnerCreateView(LoginRequiredMixin, CreateView):
"""
Sub-class of the CreateView to automatically pass the Request to the Form
and add the owner to the saved object.
"""
# Saves the form instance, sets the current object for the view, and redirects to get_success_url().
def form_valid(self, form):
print('form_valid called')
object = form.save(commit=False)
object.user = self.request.user
object.save()
return super(OwnerCreateView, self).form_valid(form)
This is my views.py
class TaskUpdateView(OwnerUpdateView):
model = Task
fields = ["title", "text", "endDate"]
class TaskCreateView(OwnerCreateView):
model = Task
fields = ["title","text","status","endDate"]
This is my urls.py:
app_name='task'
urlpatterns = [
path('', views.TaskListView.as_view(), name='all'),
path('task/<int:pk>/', views.TaskDetailView.as_view(), name='detail'),
path('task/create', views.TaskCreateView.as_view(success_url=reverse_lazy('task:all')), name='task_create'),
path('task/update/<int:pk>', views.TaskUpdateView.as_view(success_url=reverse_lazy('task:all')),
name='task_update'),
path('task/delete/<int:pk>', views.TaskDeleteView.as_view(success_url=reverse_lazy('task:all')),
name='task_delete'),
path("accounts/login/", views.login, name='login'),
path("accounts/logout/", views.logout, name='logout'),
]
And this is the models.py:
class Task(models.Model):
title=models.CharField(max_length=250)
text=models.TextField()
user=models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=False)
status=models.ForeignKey('Status',on_delete=models.SET_NULL,null=True)
startDate=models.DateTimeField(auto_now_add=True)
endDate=models.DateField(null=True)
def __str__(self):
return self.title
class Status(models.Model):
name=models.CharField(max_length=250)
def __str__(self):
return self.name
And this is where these both function work:
{%extends 'base.html'%}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table>{{ form.as_table }}</table>
<input type="submit" value="Submit">
{# <input type="submit" onclick="window.location='{% url 'project:all' %}' ; return false;" value="Cancel">#}
</form>
{% endblock %}
How can i separate each element of this form and put it in a better designed page?
Thanks
There are two ways:
Option 1:
Loop over the form fields and render them individually:
{% for field in form %}
<div class="form-group">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<span class="form-text">{{ field.help_text|safe }}</span>
{% endif %}
</div>
{% endfor %}
See docs for more.
Option 2:
You can manually create form inputs and give them the correct field name attribute. This gives you more control but also requires more work:
<div class="form-group"
<input
type="text"
name="title"
value="{{ form.title.value }}"
class="form-control {% if form.title.errors %}is-invalid{% endif %}"
>
{% if form.title.help_text%}
<span class="form-text">{{ form.title.help_text|safe }}</span>
{% endif %}
<div class="invalid-feedback">{{ form.title.errors }}</div>
</div>
<!-- now do the same for other fields -->
I have a problem whit a function, when I use the tag {{form.image_cliente}} always return a "form is invalid" and don't save nothing but if I use the tag {{form.as_p}} return a form is valid and save the field image_cliente, and I dont know why, I just want to display only the form.image_cliente in the template.
Mys form Cliente:
class ClienteForm(forms.ModelForm):
id_tipo_cliente = forms.ModelChoiceField(queryset=Tipo_cliente.objects.filter(status=1), label="Tipo de cliente" ,empty_label="Seleciona tipo", widget=forms.Select(attrs={'value':'form-control'}))
password = forms.CharField(label="Password", required=False,
widget=forms.PasswordInput)
class Meta:
model = Cliente
exclude = ['status', 'id_usuario_alt', 'fecha_creacion', 'fecha_modificacion', 'fecha_cancelacion']
fields = [
'nombres',
'apellidos',
'usuario',
'password',
'correo_electronico',
'direccion',
'telefono',
'telefono_celular',
'id_tipo_cliente',
'image_cliente',
]
labels = {'nombres':'Nombres', 'apellidos':'Apellidos', 'usuario':'Usuario', 'correo_electronico':'Correo', 'direccion':'Direccion', 'telefono':'Telefono', 'telefono_celular':'Celular', }
widgets = {
'nombres': forms.TextInput(attrs={'class':'form-control'}),
'apellidos': forms.TextInput(attrs={'class':'form-control'}),
'usuario': forms.TextInput(attrs={'class':'form-control'}),
'correo_electronico': forms.TextInput(attrs={'class':'form-control'}),
'direccion': forms.TextInput(attrs={'class':'form-control'}),
'telefono': forms.TextInput(attrs={'class':'form-control'}),
'telefono_celular': forms.TextInput(attrs={'class':'form-control'}),
'image_cliente':forms.ClearableFileInput(attrs={'multiple': True, 'class':'file', 'data-show-upload':'false', 'data-show-preview':'false'})
}
This is my def function in my views:
def subirIMGCliente(request, pk):
clientes = get_object_or_404(Cliente, pk=pk)
if request.method == 'POST':
form = ClienteForm(request.POST, request.FILES, instance=clientes)
if form.is_valid():
clientes = form.save(commit=False)
if clientes.password == '':
clientes.save(update_fields=['image_cliente'])
print('yes');
return redirect('BackEnd:cliente')
else:
print('form in not valid');
else:
form = ClienteForm(instance=clientes)
return render(request, 'back/Modulo_cliente/imagenes_cliente.html', {'form': form })
My Template
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
{{form.image_cliente}}
</div>
</div>
</div>
</br>
<br> <div class="row">
<div class="col-md-8 col-md-offset-2">
<button class="btn btn-success" type="submit">Guardar</button>
<span>Regresar</span>
</div>
</div>
</div>
</form>
the following fields are required:
usuario
nombres
direccion
apellidos
id_tipo_cliente
correo_electronico
telefono
telefono_celular
Add a required=False on them like you have on the password field, and you'll be on your way.
You add an instance for the object, and that object has values for all the required form fields, so when you load form.as_p, or any other tag that outputs the entire form, it loads with all the required fields filled out. That way, when the form is submitted, there are no validation errors. Validity checks are done over request.POST and not on the original model instance, so when the form is submitted without some of the required fields, you get validation errors.
To debug these sorts of issues, add a {{form.errors}} somewhere in your template. That's how I found the errors in your form.
It's considered best practice to display all non-field related errors in a list at the top of the form and field-related errors next to each form field.
So you'd add something like this at the top of the template:
<ol>
{% for error in form.non_field_errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
And something like this for the image_cliente form field:
{% if form.image_cliente.errors %}
<ol>
{% for error in form.image_cliente.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}
I am writing a simple view using Django Model Form, however image field fails to validate with 'This field is required' error message.
I wonder where the problem is...
Model:
class Deal(AbstractModel):
IMAGE_MAX_LENGTH = 200
place = models.ForeignKey(Place, related_name='deals', related_query_name='deal', verbose_name=_("Place"))
image = models.ImageField(default='deals/default.png', max_length=IMAGE_MAX_LENGTH, upload_to='deals', verbose_name=_("Image"))
...
View:
#login_required
def deals_create(request):
# Get place id
place_id = request.GET.get('place')
# Get place
place = Place.objects.get(id=place_id)
# Process form data
if request.method == 'POST':
form = DealsCreateForm(request.POST, request.FILES)
# Validate post data
if form.is_valid():
# Save deal data
deal = form.save(commit=False)
deal.place = place
deal.save()
# Redirect to reload page and clear post data
return HttpResponseRedirect(reverse('deal_manager:deals_pending'))
else:
form = DealsCreateForm()
return render(request, 'deal_manager/deals_create.html', {
'form': form,
'place': place,
})
Form:
class DealsCreateForm(ModelForm):
class Meta:
model = Deal
fields = [
'image', 'product_name', 'product_description',
'regular_price', 'sale_price', 'limit', 'terms',
]
Template:
{% extends "deal_manager/deal_manager.html" %}
{% load i18n %}
{% load staticfiles %}
{% block page_content_body %}
<div class="row">
<div class="span12">
<form action="{% url 'deal_manager:deals_create' %}?place={{ place.id }}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="{% trans 'Create' %}" />
</form>
</div>
</div>
<div class="gap gap-small"></div>
{% endblock page_content_body %}
Note: Form validates when I remove the image field from form meta fields.
Note: File uploads works fine with Django Admin for this model.
You'll need to include enctype="multipart/form-data" in order to bind imagefield and filefield data to the form. Without that, those fields won't validate.
{% block page_content_body %}
<div class="row">
<div class="span12">
<form enctype="multipart/form-data" action="{% url 'deal_manager:deals_create' %}?place={{ place.id }}" method="post">
...
Here's the relevant documentation: https://docs.djangoproject.com/en/stable/ref/forms/api/#binding-uploaded-files-to-a-form
I want to insert data from form into database. Following are the models:
from django.db import models
from django.forms import ModelForm
# Create your models here.
class Recipe(models.Model):
title=models.CharField(max_length=200)
class User(models.Model):
fname=models.CharField(max_length=30)
lname=models.CharField(max_length=30)
class Recipe2User(models.Model):
user_id=models.ForeignKey(User)
recipe_id=models.ForeignKey(Recipe)
class Ingredient(models.Model):
recipe_id=models.ForeignKey(Recipe)
name=models.CharField(max_length=200)
class Prepration_step(models.Model):
recipe_id=models.ForeignKey(Recipe)
step=models.CharField(max_length=1000)
class RecipeForm(ModelForm):
class Meta:
model=Recipe
fields=['title']
I have created a form which takes recipe name, ingredients and preparation steps.
Below is the view which handles the post:
def createRecipe_form(request):
c = {}
c.update(csrf(request))
return render_to_response('create.html',c)
def create_recipe(request):
if request.method == 'POST':
form=RecipeForm(request.POST)
if form.is_valid():
title=form.cleaned_data['recipe_name']
r=Recipe(title)
r.save()
return HttpResponseRedirect('display.html')
else:
form=RecipeForm()
return render(request, 'create.html', {
'form': form,
})
and this is the html form I have created
<html>
<head>
<title>Create-Recipe</title>
</head>
<body>
<h1>My Recipe-Create a recipe</h1>
<form action="/recipe/submit-recipe/" method="post">
{% csrf_token %}
{% if errors %}
<div id="errors">
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
Title:
<input type="text" name="recipe_name" placeholder="Ex:Gobi Masala"><br>
Ingredient:
<textarea rows="4" name="recipe_ingredient" cols="50" placeholder="Ex: 2 cups rice,1/2 teaspoon oil"></textarea><br>
Preparation:
<textarea rows="4" name="recipe_preparation" cols="50" placeholder="Ex:Pour oil in frying pan,Fry onions till they turn light brown"></textarea><br>
<input type="submit" value="OK">
</form>
Please tell me how to go about inserting recipe title, ingredients and steps in Recipe, Ingredient and Prepration_step table as I am newbie to django.
Thanks
forms.py
class RecipeForm(ModelForm):
class Meta:
model = Recipe
views.py
def create_recipe(request):
if request.method == 'POST':
form=RecipeForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('app_name:url_name'))
return render(request, 'create.html', {
'form': RecipeForm(),
})
html
<form action="/recipe/submit-recipe/" method="post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="OK">
</form>