ValidationError message doesn't appear in my own form - django

I created a custom registration form:
class MyRegistrationForm(UserCreationForm):
mobile = models.CharField(max_length=16)
address = models.CharField(max_length=100)
class Meta():
model = CustomUser
fields = ['username', 'password1', 'password2', 'first_name', 'last_name', 'email', 'mobile', 'address']
def clean_mobile(self):
mobile = self.cleaned_data['mobile']
if CustomUser.objects.filter(mobile=mobile).exists():
raise ValidationError('Mobile already exists')
return mobile
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
user.mobile = self.cleaned_data['mobile']
user.address = self.cleaned_data['address']
if commit:
user.save()
return user
And in my template, I don't write just `{{form}}', instead I use my bootstrap template for registration. It looks like:
<form class="form-horizontal" action="{% url 'register' %}" method="post">
{% csrf_token %}
<div class="control-group">
<label class="control-label" for="username1" >Ім'я користувача <sup>*</sup></label>
<div class="controls">
<input type="text" id="username1" placeholder="Нік" name="username">
</div>
</div>
<div class="control-group">
<label class="control-label" for="password_1" >Пароль <sup>*</sup></label>
<div class="controls">
<input type="password" id="password_1" placeholder="Введіть пароль" name="password1">
</div>
</div>
<div class="control-group">
<label class="control-label" for="password_2" >Повторіть пароль <sup>*</sup></label>
<div class="controls">
<input type="password" id="password_2" placeholder="Повторіть пароль" name="password2">
</div>
</div>
But when clean_mobile method is called and raise ValidationError, no errors aren't showed. How to solve this issue? Or maybe I can use in template {{form}} but I need to use bootstrap css?

You need to include {{ form.mobile.errors }} to display errors for your mobile field.
See the working with form templates docs for more information.
You might want to investigate django crispy forms, which makes it easy to render bootstrap forms.

Related

How to Add Subscribe option in a Django Website

I am trying to add a subscribe to newsletter option on a django website. When a visitor enters
a valid email address it will be stored in the database. The subscription form is part of the base.html template.
All other templates of the website extend this template. I wish to implement this in a DRY way.
This is how I am trying to do it :
forms.py :
from dataclasses import fields
from django import forms
from . models import Subscribers, MailMessage
class SubcribersForm(forms.ModelForm):
class Meta:
model = Subscribers
fields = ['email', ]
views.py :
def base(request):
if request.method == 'POST':
form = SubcribersForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
form = SubcribersForm()
context = {'form': form}
return render(request, 'base.html', context)
The template: base.html
<form method = "POST" class="signup-form form-inline justify-content-center pt-3">
{% csrf_token %}
<div class="form-group">
<label class="sr-only" for="semail">{{context}}</label>
<input type="email" id="semail" name="semail1" class="form-control mr-md-1 semail" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Subscribe</button>
</form>
models.py :
class Subscribers(models.Model):
email = models.EmailField(null=True)
date = models.DateTimeField(auto_now_add=True)
def __str__self(self):
return self.email
In the backend, I can see that the Subscribers table has been created. However, when I enter any email address from the home
page and click subscribe button it does not store it in the database. What could be the issue here?
It could be that you have no action declared in your form. Assuming you have a url like this:
path('add-subscriber/', base, name='base'),
...your form would need a way to call it upon submit, like this:
<form method = "POST" action="{% url 'base' %}" class="signup-form form-inline justify-content-center pt-3">
{% csrf_token %}
<div class="form-group">
<label class="sr-only" for="semail">{{context}}</label>
<input type="email" id="semail" name="semail1" class="form-control mr-md-1 semail" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Subscribe</button>
</form>

''TypeError at /user expected string or bytes-like object'' on submitting the for in django?

When I submitting the form in django it is giving error ''TypeError at /user expected string or bytes-like object''.
This is my staff models
class staff(models.Model):
id = models.AutoField
name = models.CharField(max_length=250)
role = models.CharField(max_length=250)
salary = models.CharField(max_length=250)
address = models.CharField(max_length=250)
number = models.CharField(max_length=250)
date = models.DateField()
This is my user views.
def user(request):
if request.method == "POST" :
name = request.POST['name']
role = request.POST['role']
salary = request.POST['salary']
address = request.POST['address']
number = request.POST['number']
date = DateTimeField()
ins = staff(name=name, role=role, salary=salary, address=address, date=date, number=number)
ins.save()
staffs = staff.objects.all()
return render(request, "salary/user.html", {'staff': staffs})
and this is form of template user.html
<form class="forms-sample" action="/user" method="post">
{% csrf_token %}
<div class="form-group row">
<label for="exampleInputUsername2" class="col-sm-3 col-form-label">Name:</label>
<div class="col-sm-9">
<input type="text" name="name" id="name" class="form-control" id="exampleInputUsername2" placeholder="Username">
</div>
</div>
<div class="form-group row">
<label for="exampleInputUsername2" class="col-sm-3 col-form-label">Role:</label>
<div class="col-sm-9">
<input type="text" name="role" id="role" class="form-control" id="exampleInputUsername2" placeholder="Role">
</div>
</div>
<div class="form-group row">
<label for="exampleInputUsername2" class="col-sm-3 col-form-label">Salary:</label>
<div class="col-sm-9">
<input type="text" name="salary" id="salary" class="form-control" id="exampleInputUsername2" placeholder="Salary">
</div>
</div>
<div class="form-group row">
<label for="exampleInputUsername2" class="col-sm-3 col-form-label">Address:</label>
<div class="col-sm-9">
<input type="text" name="address" id="address" class="form-control" id="exampleInputUsername2" placeholder="Address">
</div>
</div>
<div class="form-group row">
<label for="exampleInputUsername2" class="col-sm-3 col-form-label">Mobile no.:</label>
<div class="col-sm-9">
<input type="text" name="number" id="number" class="form-control" id="exampleInputUsername2" placeholder="Mobile no.">
</div>
</div>
<button type="submit" class="btn btn-primary mr-2">Submit</button>
<button class="btn btn-dark">Cancel</button>
</form>
I am new in django and i not know what the problem is.
Thanks for helping in advance.
It makes no sense to pass a reference to the AutoField model field in your model, you should construct a field, so:
class staff(models.Model):
id = models.AutoField()
# &vellip;
as for the date field, you can work with auto_now_add=True [Django-doc] to automatically fill in the current day:
class staff(models.Model):
# &vellip;
date = models.DateField(auto_now_add=True)
then this can be omitted while constructing a staff object:
def user(request):
if request.method == "POST" :
name = request.POST['name']
role = request.POST['role']
salary = request.POST['salary']
address = request.POST['address']
number = request.POST['number']
# no date=… &downarrow;
ins = staff.objects.create(name=name, role=role, salary=salary, address=address, number=number)
ins.save()
staffs = staff.objects.all()
return render(request, "salary/user.html", {'staff': staffs})
It might however be better to work with Django forms to validate, clean and fill in data from a POST request.
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: Models in Django are written in PascalCase, not snake_case,
so you might want to rename the model from staff to Staff.

how to display Django model based form to the center of page(Crispy form)

I am trying to use the crispy form for Django model-based form. I have referred a few questions already asked but no luck I did not found the way how to centralize the Crispy form.
Please find the below code.
forms.py
class SignUpForm(forms.ModelForm):
username = forms.CharField(label=' Enter Username',widget=forms.TextInput(attrs={'placeholder': 'LDAPID/AppleConnect'}))
password = forms.CharField(label='Enter Password',widget=forms.PasswordInput(attrs={'placeholder': 'alphanumeric password'}))
User._meta.get_field('email')._unique = True
email = forms.CharField(label='Enter Email ID', widget=forms.EmailInput(attrs={'placeholder': 'abc#apple.com'}))
# username = forms.CharField(label=_("Enter LDAP ID"), widget=MyPasswordInput
def __init__(self, *args, **kwargs):
super(SignUpForm, self).__init__(*args, **kwargs)
# If you pass FormHelper constructor a form instance
# It builds a default layout with all its fields
self.helper = FormHelper(self)
self.helper.form_class = 'vertical-form'
# You can dynamically adjust your layout
self.helper.layout.append(Submit('save', 'save'))
class Meta:
model = User
fields = ['username', 'password', 'email', 'first_name', 'last_name']
help_texts = {
'username': None,}
HTML file:
<div class="jumbotron">
<div class="container" align=''>
<div class="alert warning">
<span class="closebtn" onclick="this.parentElement.style.display='none';">×</span>
Please Read the below Instruction Carefully.<br>
<strong>Alert!</strong> <br>
1. In
<span2> Username</span2>
enter your ldap ID and in
<span2>Email</span2>
field enter apple Email.<br>&nbsp&nbsp
2.Once the Account created user will not have Access to the respective Portal.To get Access please file
radar with business justification(User should be part of vendor Company group).
</div>
<br>
<div class="col-md-12 well">
<div class="form-row" col-md-8>
<div class="form-group col-md-4 mb-0 align=center">
<form action="" method="POST">
{{form|crispy}}
{% csrf_token %}
<input type="submit" class="btn btn-primary" name="" value="Click to SignUp"
onclick="return confirm('Thank you redirecting you to login Page.');">
</form>
</div>
</div>
</div>
</div>
{%endblock%}
Image :
any help/Suggestion on this would be appreciated.

django form not submitting due to slug and foreign key

My django cabin form is not submitting. I have applied foreign key and slug in my cabin's model and after that my form stopped getting submitted. whenever I enter all the fields and hit submit button,the form page is getting reloaded and no data is getting submitted.Most Importantly it is not showing any error so that I can fix it.I have tried and searched a lot about it and tried different things but still it didn't work. I am stuck to it. Please help!!
class Centre(models.Model):
name= models.CharField(max_length=50, blank=False, unique=True)
address = models.CharField(max_length =250)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$',
message="Phone number must be entered in the format: '+999999999'. Up to 10 digits allowed.")
contact = models.CharField(max_length=100, blank=False)
phone = models.CharField(validators=[phone_regex], max_length=10, blank=True) # validators should be a list
slug = models.SlugField(unique=False)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Centre, self).save(*args, **kwargs)
class Cabin(models.Model):
random_string = str(random.randint(100000, 999999))
centre_name = models.ForeignKey(Centre, on_delete=models.CASCADE,blank=True,null=True)
code = models.CharField(max_length=6, blank=False, unique=True, default=random_string)
total_seats = models.IntegerField(blank='False')
category=models.CharField(max_length=100, default=False)
booked_date=models.DateField(blank='False')
released_date=models.DateField(blank='False')
price=models.IntegerField(blank=False, default=None)
slug = models.SlugField(unique=False,default=None)
def save(self, *args, **kwargs):
self.slug = slugify(self.category)
super(Cabin, self).save(*args, **kwargs)
In views.py file
class CabinCreateView(CreateView):
fields = '__all__'
model = Cabin
success_url = reverse_lazy("NewApp:logindex")
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.cabin = Cabin.objects.filter(slug=self.kwargs['slug'])[0]
self.object.save()
return HttpResponseRedirect(self.get_success_url())
In my cabin template,
<div class="row">
<div class="col-md-6">
<form method="POST">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="col col-md-12">
<div class="fieldWrapper" >
{{ form.centre_name.errors }}
<div class="form-group col col-md-3">
<label>Centre Name</label>
{{form.centre_name}}
</div>
<div class="form-group col col-md-3" style="float:right; margin-top=-80px;width=200%">
<label for="{{form.code.id_for_label}" style="margin-left:200px;width:200%;white-space:nowrap;">Code</label>
<input type="text" placeholder="Code" value="{{form.code.value}}" name="code" maxlength="6" id="id_code" style="width:500px; margin-left:200px;">
</div>
</div>
<div class="col col-md-12">
<div class="form-group col col-md-3" style="float:right; margin-top=-80px;">
<label for="{{form.total_seats.id_for_label}" style="margin-left:200px;width:200px;white-space:nowrap;">seats</label>
<input type="text" placeholder="seats" name="total_seats" id="id_total_seats" style="width:500px; margin-left:200px;">
</div>
<div class="fieldWrapper" >
{{ form.category.errors }}
<div class="form-group col col-md-3" >
<label for="{{form.category.id_for_label}" style="margin-top:-40px">Category</label>
<input type="text" name="category" maxlength="100" id="id_category" placeholder="Category" style="width:500px";>
</div></div></div>
<div class="col col-md-12">
<div class="fieldWrapper" >
{{ form.released_date.errors }}
<div class="form-group col col-md-3" style="float:right; margin-top=-80px;">
<label for="{{form.released_date.id_for_label}" style="margin-left:200px;width:200px;white-space:nowrap;">released date</label>
<input type="text" placeholder="%yyyy-mm-dd" name="released_date" id="id_released_date" style="width:500px; margin-left:200px;">
</div>
</div>
<div class="fieldWrapper" >
{{ form.booked_date.errors }}
<div class="form-group col col-md-3" >
<label for="{{form.booked_date.id_for_label}" style="margin-top:-40px">booked date</label>
<input type="text" name="booked_date" id="id_booked_date" placeholder="%yyyy-mm-dd" style="width:500px";>
</div>
</div>
</div>
<div class="col col-md-12">
<div class="form-group col col-md-3" >
<label for="{{form.price.id_for_label}" style="margin-top:-40px">price</label>
<input type="text" name="price" maxlength="10" id="id_price" placeholder="in rupees" style="width:500px";>
</div>
</div>
<div class="form-group col col-md-3" >
<input type="submit" onclick="comparedate()" value="Save" class="btn btn-primary" style=" height:30px;width:80px;padding-bottom:2em;"/>
</div></div>
</form>
</div></div></div></div></div></div></div></div></div></div>
It looks like your problem is in your views.py file. You are telling the view that it should build a form including __all__ of the fields on the model, but in your template you don't include the slug field. Since you have overridden the save method on the Cabin model to populate the slug field, I guess you don't want that displayed in the template.
You have two options for fixing this. You could add a hidden field to the template containing the slug field. Or, what I think is a better option, you can change the fields attribute on your view to exclude the slug field.
class CabinCreateView(CreateView):
fields = ('centre_name', 'code', 'total_seats', 'category', 'booked_date', 'released_date', 'price',)
model = Cabin
success_url = reverse_lazy("NewApp:logindex")
P.S. This isn't a problem you are asking about, but I couldn't help noticing that you have what looks like multiple broken variables in your template. You might want to check if your label for="" attributes are working as expected.

how to save many to many field using django custom forms

how can i save many courses to the student table .I want to keep my design like this.This code is not saving the many to many field(courses) through AddStudentForm.It returns an error with courses variable.If i used CharField instead of ManyToManyField in models for courses then the code works perfectly,but when i use ManyToManyField then it is not working.
it throws courses when i used form.errors .If i didn't use form.errors then it doesn't give any error neither saves the data.
how can i save many courses to the student table .I want to keep my design like this.This code is not saving the many to many field(courses) through AddStudentForm.It returns an error with courses variable.
models.py
class Course(models.Model):
title = models.CharField(max_length=250)
price = models.IntegerField(default=0)
duration = models.CharField(max_length=50)
def __str__(self):
return self.title
class Student(models.Model):
name = models.CharField(max_length=100)
courses = models.ManyToManyField(Course)
email = models.EmailField()
image = models.ImageField(upload_to='Students',blank=True)
def __str__(self):
return self.name
forms.py
class AddStudentForm(forms.ModelForm):
# courses = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Course.objects.all())
class Meta:
model = Student
fields = ['name','courses','email','image']
def __init__(self, *args, **kwargs):
super(AddStudentForm, self).__init__(*args, **kwargs)
self.fields["courses"].widget = CheckboxSelectMultiple()
self.fields["courses"].queryset = Course.objects.all()
views.py
def addstudent(request):
courses = Course.objects.all()
if request.method == 'POST':
form = AddStudentForm(request.POST,request.FILES)
if form.is_valid():
student = form.save(commit=False)
course = form.cleaned_data['courses']
student.courses = course
student.save()
# student.courses.add(course)
# student.save_m2m()
# student.courses.set(course) # this method also didn't helped me
messages.success(request, 'student with name {} added.'.format(student.name))
return redirect('students:add_student')
else:
# messages.error(request,'Error in form.Try again')
return HttpResponse(form.errors) # this block is called and returns courses
else:
form = AddStudentForm()
return render(request,'students/add_student.html',{'form':form,'courses':courses})
add_student.html
<form action="{% url 'students:add_student' %}"
method="post"
enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<h5>Full Name <span class="text-danger">*</span>
</h5>
<div class="controls">
<input type="text" name="name" class="form-
control" > </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.title}}">
<label for="course-{{course.id}}">{{course.title}}
</label>
{% endfor %} # i think the problem is here.
</div>
</div>
<div class="form-group">
<h5>Email <span class="text-danger">*</span></h5>
<div class="controls">
<input type="text" name="email" class="form-
control" required> </div>
</div>
</div>
<div class="form-group">
<h5>Image <span class="text-danger">*</span></h5>
<div class="controls">
<input type="file" name="image" class="form-control" > </div>
</div>
<div class="text-xs-right">
<button type="submit" class="btn btn-info">Add</button>
</div>
</form>
You need to save first before you can assign m2m, the system needs the primary key of the Student model before it can insert into the m2m table.
if form.is_valid():
student = form.save(commit=False)
course = form.cleaned_data['courses']
student.save()
# this will save by itself
student.courses.set(course)