None value passed on editing the form on HTML - python

I am editing the Firtname and Lastname fetched from auth_User. When I edit the name and save, the None value is passed to the names. On verifying page source I dont see any error.
form.py
from django.contrib.auth.models import User
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name','last_name', 'email')
view.py
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user,
data=request.POST)
if user_form.is_valid():
user_form.save()
messages.success(request, 'Profile updated successfully!')
else:
messages.success(request, 'Error updating your profile!')
else:
user_form = UserEditForm(instance=request.user)
return render(request,
'account/edit.html',
{'user_form': user_form})
HTML
<div class="form-row">
<label class="col-sm-2 control-label" placeholder="First Name">First Name:</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="first_name" value="{{ user_form.first_name.value }}">
</div>
<label class="col-sm-2 control-label">Last Name:</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="last_name" value="{{ user_form.last_name.value }}">
</div>
</div>
<div class="form-row">
<label for="email" class="col-sm-2 control-label">Email address:</label>{{ user_form.email }}
<div class="col-sm-4">
<input type="email" class="form-control" id="email" value="{{ user_form.email.value }}">
</div>
</div>

You do not have any name attributes on your form fields, so no data will be submitted. Add a name attribute to both fields:
<input name="first_name" type="text" class="form-control" id="first_name" value="{{ user_form.first_name.value }}" >
<!-- ^^^^ note new name attribute -->
and:
<input name="last_name" type="text" class="form-control" id="last_name" value="{{ user_form.last_name.value }}" >
Note also that you have specified email in the fields on your form, but there is no email field in your HTML, which will also cause problems. You should either add that field to your HTML or remove it from the form definition.
You might also consider using Django's form helpers to render the fields.

The <input> tags you have created in your template do not include name attributes. When you attempt to submit the form, these items will not be sent.
The correct name for each form field can be accessed using the html_name attribute, eg:
{{ user_form.first_name.html_name }}
#solarissmoke mentioned that you should consider using the Django form helpers, and I strongly agree. If you don't like how default widgets appear in your HTML, you can add classes when you create the form:
from django.contrib.auth.models import User
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name','last_name', 'email')
widgets = {
'first_name': forms.TextInput(attrs={'class': 'form-control'}),
'last_name': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
}
Then in your template:
<div class="form-row">
<label for="{{ user_form.first_name.auto_id }}" class="col-sm-2 control-label" placeholder="First Name">First Name:</label>
<div class="col-sm-4">
{{ user_form.first_name }}
</div>
<label for="{{ user_form.last_name.auto_id }}" class="col-sm-2 control-label">Last Name:</label>
<div class="col-sm-4">
{{ user_form.last_name }}
</div>
</div>
<div class="form-row">
<label for="{{ user_form.email.auto_id }}" class="col-sm-2 control-label">Email address:</label>
<div class="col-sm-4">
{{ user_form.email }}
</div>
</div>

Related

TypeError in django while creating model instances

I have a model onlinebooking and I am trying to save the data the user inputs. However I am getting the error TypeError at /onlinebooking/
onlinebooking() got an unexpected keyword argument 'name'. I get this error after clicking the register button.
Here is my model:
class onlinebooking(models.Model):
name = models.CharField(max_length=30)
email = models.CharField(max_length=30)
phone_number = models.IntegerField()
room_type = models.CharField(max_length=10)
booking_date = models.DateField()
views.py
from django.shortcuts import render,redirect
from .models import onlinebooking
def onlinebooking(request):
if request.method == "POST":
name = request.POST['Name']
email = request.POST['email']
phone_number = request.POST['phone_no']
room_type = request.POST['room_type']
booking_date = request.POST['booking_date']
online = onlinebooking(name=name,email=email,phone_number=phone_number,room_type=room_type,booking_date=booking_date)
online.save()
return redirect('/')
else:
return render(request,'hotel/onlinebooking.html')
form used:
<form action="/onlinebooking/" method="post">
{% csrf_token %}
<div class="text-primary">
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputEmail4">Name</label>
<input type="text" class="form-control" id="inputEmail4" name="Name" required>
</div>
<!-- <div class="form-group col-md-6">
<label for="lastname">Last name</label>
<input type="text" class="form-control" id="lastname"
name="lastname" required>
</div> -->
<div class="form-group col-md-6">
<label for="inputPassword4">Email</label>
<input type="text" class="form-control" id="inputPassword4" name="email" required>
</div>
<div class="form-group col-md-6">
<label for="inputPassword4">Phone no</label>
<input type="text" class="form-control" id="inputPassword4" name="phone_no" required>
</div>
<div class="form-group col-md-6">
<label for="inputState">Room Type</label>
<select id="inputState" class="form-control" name="room_type">
<option selected>Standard</option>
<option>Delux</option>
<option>Premium</option>
</select>
</div>
<div class="form-group col-md-6">
<label for="bookingtime">Booking Date</label>
<input type="date" id="bookingtime" name="booking_date" required>
</div>
<div class="text-center">
<input type="submit" value="Register" name="submit-emp" class="btn btn-primary col-sm-3 btn-user ">
</div>`
I guess there is some error with my models as I can access all the entries of the user. i think its some silly mistake from my side. Please help me out here. :)
You are overriding the import name with the class name in this file itself.
Try this:
from django.shortcuts import render,redirect
from . import models
def onlinebooking(request):
if request.method == "POST":
name = request.POST['Name']
email = request.POST['email']
phone_number = request.POST['phone_no']
room_type = request.POST['room_type']
booking_date = request.POST['booking_date']
online = models.onlinebooking(name=name,email=email,phone_number=phone_number,room_type=room_type,booking_date=booking_date)
online.save()
return redirect('/')
else:
return render(request,'hotel/onlinebooking.html')

Postgresql is not getting data from form

I'm learning django now, and i'm facing a problem, I create a form to submite data in my database, but the problem is when i click on submit button, postgres isn't receiving data, I cant understand the problem.
This is my contact form
This is my database
This is my html code
<form action="." method='post' class="p-5 bg-white">
<h2 class="h4 text-black mb-5">Contact Form</h2>
{% csrf_token %}
<div class="row form-group">
<div class="col-md-6 mb-3 mb-md-0">
<label class="text-black" for="fname">First Name</label>
<input type="text" id="fname" class="form-control rounded-0">
</div>
<div class="col-md-6">
<label class="text-black" for="lname">Last Name</label>
<input type="text" id="lname" class="form-control rounded-0">
</div>
</div>
<div class="row form-group">
<div class="col-md-12">
<label class="text-black" for="email">Email</label>
<input type="email" id="email" class="form-control rounded-0">
</div>
</div>
<div class="row form-group">
<div class="col-md-12">
<label class="text-black" for="subject">Subject</label>
<input type="subject" id="subject" class="form-control rounded-0">
</div>
</div>
<div class="row form-group">
<div class="col-md-12">
<label class="text-black" for="message">Message</label>
<textarea name="message" id="message" cols="30" rows="7" class="form-control rounded-0" placeholder="Leave your message here..."></textarea>
</div>
</div>
<div class="row form-group">
<div class="col-md-12">
<input type="submit" value="Send Message" class="btn btn-primary mr-2 mb-2">
</div>
</div>
</form>
This is my models.py
from django.db import models
class Form(models.Model):
fname=models.CharField(max_length=300)
lname=models.CharField(max_length=300)
email=models.EmailField()
subject=models.CharField(max_length=300)
message=models.TextField()
This is my views.py
from django.shortcuts import render
from .models import Form
def test(request):
if request.method == 'POST':
request.POST.get('fname')
request.POST.get('lname')
request.POST.get('email')
request.POST.get('subject')
request.POST.get('message')
post=Form()
post.fname= request.POST.get('fname')
post.lname= request.POST.get('lname')
post.email= request.POST.get('email')
post.subject= request.POST.get('subject')
post.message= request.POST.get('message')
post.save()
else:
return render(request,'test.html')
1st. In the form action="." is not necessary as if action is empty it will be sent to the current view itself.
2nd. I suggest using Model Forms which are a lot easier.
Let's say the model name is M1.
models.py
from django.db import models
class M1(models.Model):
fname = models.CharField(max_length=300)
lname = models.CharField(max_length=300)
email = models.EmailField()
subject = models.CharField(max_length=300)
message = models.TextField()
forms.py
from django import forms
M1Form(forms.modelForm):
class Meta:
model = M1
views.py
from django.shortcuts import render
from .models import M1
from .forms import M1Form
def test(request):
if request.method == "POST":
form = M1Form(request.POST)
if form.is_valid():
form.save()
else:
return render(request, "test.html")
else:
return render(request, "test.html")
3rd. If you look at the Templates:
<input type="email" id="email" class="form-control rounded-0">
it does not have an attribute "name" in it. If you want email in request.POST It should be written like
<input type="email" id="email" name="email" class="form-control rounded-0">
Please keep in mind that the name should be the same as the model name (Since we are not overwitting the Form).
For more Documentation:
https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/

form.is_valid() not working when using django forms for updating information to the databse

So I wanna be able to update information of a router in the database using a form, I wanna have a form pre-populated with that specific router details. The problem is that form.is_valid() is not working
I tried using {{ form.errors }} {{ form.non_field_errors }} and print(form.errors) but none of them worked
views.py (incomplete)
def info_router(request, pk):
rout = Routers.objects.get(sn=pk)
if request.method == 'GET': # Insert the info in forms
form = UpdateRouter()
rout = Routers.objects.get(sn=pk)
args = {'router': rout}
return render(request, "router_info.html", args)
if request.POST.get('delete'):
# Delete router
rout.delete()
messages.warning(request, 'Router was deleted from the database!')
return redirect("db_router")
if request.method == 'POST':
#Updating the form
form = UpdateRouter(instance=Routers.objects.get(sn=pk))
print(form)
print(form.errors)
if form.is_valid():
data = UpdateRouter.cleaned_data
mac = data['mac']
print(mac)
return HttpResponseRedirect('db_router')
else:
print("Invalid form")
return render(request, "db_router.html", {'form': form})
forms.py
class UpdateRouter(ModelForm):
class Meta:
model = Routers
fields = ['model', 'ip_addr', 'name', 'sn', 'mac']
template
<form class="form-horizontal" action="" method="post">
{% csrf_token %}
<div class="form-group"> <!-- Form with the router details -->
<label class="control-label col-sm-2" for="text">Serial number:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="text" name="sn" value="{{ router.sn }}" readonly>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="text">Model:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="text" value="{{ router.model }}" name="model" readonly>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="text">Ip address:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="text" value="{{ router.ip_addr }}" name="ip_addr">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="text">Name:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="text" value="{{ router.name }}" name="name">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="text">Mac address:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="text" value="{{ router.mac }}" name="mac">
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="text">Extra info:</label>
<div class="col-sm-10">
<textarea class="form-control" name="extra_info" id="FormControlTextarea" rows="3">Example of some info</textarea>
</div>
</div>
<div class="form-group" style="margin-top: 20px;">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Update</button> <!-- Responsible for updating the router -->
Cancel
<button type="button" class="btn btn-danger" data-toggle="modal" data-target="#myModal" style="float: right"> <!-- Responsible for the delete modal to open -->
Delete
</button>
</div>
</div>
</form>
You never passed request.POST and rquest.FILES. If you want to update the fields and files, you need to form.save() your form:
if request.method == 'POST':
#Updating the form
form = UpdateRouter(request.POST, request.FILES, instance=Routers.objects.get(sn=pk))
print(form)
print(form.errors)
if form.is_valid():
data = form.cleaned_data
mac = data['mac']
form.save()
print(mac)
return redirect('db_router')
else:
print("Invalid form")
If you do not pass request.POST and/or request.FILES, then Django does not consider the form filled in, and it is never considered valid.
If you pass both files and data, then you need to add the enctype="multipart/form-data" to your <form> tag:
<form enctype="multipart/form-data" class="form-horizontal" action="" method="post">
<!-- -->
</form>
you need to create a bound_form
form = UpdateRouter(request.POST)
form = UpdateRouter(request.POST) binds the data to the form class. then validate
the inputs using is_valid().

POST no save to model. return "this field is required" error on Django

Hi friends I am new for Django
I want to make a form with bootstrap.
When I click submit Button Post Data is
<QueryDict: {'csrfmiddlewaretoken': ['mjzoKZ1GPuHMCR6LQwNpUxDW0Y1KyxRgySSynPSOU7eHK8Zlm5dgqvWwhXpD3F0M'], '<input type="text" name="borclu" maxlength="36" required id="id_borclu">': ['asfasf'], '<input type="email" name="borclu_mail" maxlength="25" required id="id_borclu_mail">': ['asdasd'], '<textarea name="borcluAdres" cols="40" rows="10" maxlength="80" required id="id_borcluAdres">\r\n</textarea>': ['asdasd'], '<input type="text" name="borcluTelefon" maxlength="11" required id="id_borcluTelefon">': ['asdasd'], '<input type="number" name="tutar" required id="id_tutar">': ['asdasd'], '<input type="text" name="cek_tarih" required id="id_cek_tarih">': ['12-02-2019']}>
But data no saved to model
My model like that;
class cekler(models.Model):
borclu=models.CharField(max_length=36,verbose_name="Keşideci")
borcluAdres=models.TextField(max_length=80,verbose_name="Keşideci Adresi")
borclu_mail = models.EmailField(max_length=25,verbose_name="Keşideci E Posta Adresi")
borcluTelefon=models.CharField(max_length=11,verbose_name="Keşideci Telefon")
tutar=models.IntegerField(verbose_name="Tutar")
bankalar = (
('Ziraat Bankası', 'Ziraat Bankası'),
('YapıKredi Bankası', 'YapıKredi Bankası'),
('Vakıflar Bankası', 'Vakıflar Bankası'),
('Teb', 'TEB'),
)
banka=models.CharField(max_length=20, choices=bankalar, verbose_name="Banka Adı:")
cek_tarih=models.DateField(verbose_name="Çek Tarihi")
son_tarih = models.DateTimeField(blank=True, null=True)
def _get_gecen_gun(self):
"Returns the person's full name."
day=date.today()-self.cek_tarih
ggun = str(day)
ggun = ggun.split(' ')[0]
return '%s' % (ggun)
gecenGun = property(_get_gecen_gun)
def __str__(self):
return self.borclu
def save(self, *args, **kwargs):
if not self.pk:
self.son_tarih = self.cek_tarih + datetime.timedelta(days=80)
super(cekler, self).save(*args, **kwargs)
class Meta:
ordering = ['-id']
My Form.py;
from django import forms
from .models import cekler
class CekForm(forms.ModelForm):
class Meta:
model=cekler
fields=[
'borclu',
'borcluAdres',
'borclu_mail',
'borcluTelefon',
'tutar',
'banka',
'cek_tarih',
]
My Template
<form method="post">
{% csrf_token %}
<div class="container">
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputEmail4">Keşideci Adı</label>
<input type="text" name='{{ form.borclu }}' class="form-control" >
</div>
<div class="form-group col-md-6">
<label for="inputPassword4">Borçlu Mail</label>
<input type="text" name='{{ form.borclu_mail }}' class="form-control" >
</div>
</div>
<div class="form-group">
<label for="inputAddress">Borçlu Adres</label>
<input type="text" name='{{ form.borcluAdres }}' class="form-control" >
</div>
<div class="form-group">
<label for="inputAddress2">Borçlu Telefon</label>
<input type="text" name='{{ form.borcluTelefon }}' class="form-control" >
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputCity">Tutar</label>
<input type="text" name='{{ form.tutar }}' class="form-control" >
</div>
<div class="form-group col-md-4">
<label for="inputState">Banka</label>
<select id="inputState" class="form-control">
{% for value in form.banka %}
<option >{{ value }}</option>
{% endfor %}
</select>
</div>
<div class="form-group col-md-2">
<label for="inputZip">Çek Tarihi</label>
<input type="text" name='{{ form.cek_tarih }}' class="form-control" >
</div>
</div>
<input type="submit" class="btn btn-primary" value="Ekle">
</div>
</form>
I think problem from my Bootstrap implementation. Before this implemantation I use form with 'form.as_p' and it was correct.
Now when I click button anything happen. No error. But data no save on my model.
You're putting the wrong thing in your template. You should be able to see from the submitted data that each field has some HTML as its key, which is obviously wrong.
Instead of name='{{ form.borclu }}' etc you should probably do name='{{ form.borclu.name }}'.

Validating and displaying errors in custom Django form

When I use form.as_p to display my form and, for example, I click on Submit button without fill any field, it shows error messages asking me to fill the required fields. However, when I customize the output of my html template, it doesn't validate the fields and doesn't show any error message. My forms.py:
# forms.py
class SignUpForm(forms.ModelForm):
username = forms.CharField(label='Username', max_length=75, widget=forms.TextInput(attrs={'placeholder' : 'Username'}))
email = forms.EmailField(label='Email', max_length=255)
first_name = forms.CharField(label='First Name', max_length=75)
last_name = forms.CharField(label='Last Name', max_length=75)
birthday = forms.DateField(label='Birthday')
gender = forms.ChoiceField(choices = User.GENDER_CHOICES)
class Meta:
model = User
fields = ['username', 'password', 'email', 'first_name', 'last_name', 'birthday', 'gender']
widgets = {
'password': forms.PasswordInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
'birthday': forms.DateInput(attrs={'class': 'form-control'}),
}
def save(self, commit=True):
user = super(SignUpForm, self).save(commit=False)
user.username = self.cleaned_data['username']
user.set_password(self.cleaned_data['password'])
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.birthday = self.cleaned_data['birthday']
user.gender = self.cleaned_data['gender']
if commit:
user.save()
return user
My HTML template is like this:
# registration.html
<form class="form-signin" action="/register/" method="post">
<h2 class="form-signin-heading">registration now</h2>
<div class="login-wrap">
<p>Enter your personal details below</p>
<input type="text" class="form-control" placeholder="{{ form.first_name.label }}" name="{{ form.first_name.name }}" id="id_{{ form.first_name.name }}" maxlength="75" autofocus>
<input type="text" class="form-control" placeholder="{{ form.last_name.label }}" name="{{ form.last_name.name }}" id="id_{{ form.last_name.name }}" maxlength="75" autofocus>
<input type="text" class="form-control" placeholder="{{ form.email.label }}" name="{{ form.email.name }}" id="id_{{ form.email.name }}" maxlength="255" autofocus>
<div class="radios">
{% for choice in form.gender.field.choices %}
<label class="label_radio col-lg-4 col-sm-4" for="">
<input name="{{ form.gender.name }}" id="radio-01" value="{{choice.0}}" type="radio" checked /> {{ choice.1 }}
</label>
{% endfor %}
</div>
<p> Enter your account details below</p>
<input type="text" class="form-control" placeholder="{{ form.username.label }}" name="{{ form.username.name }}" id="id_{{ form.username.name }}" autofocus>
<input type="password" class="form-control" placeholder="{{ form.password.label }}" name="{{ form.password.name }}" id="id_{{ form.password.name }}">
<label class="checkbox">
<input type="checkbox" value="agree this condition"> I agree to the Terms of Service and Privacy Policy
</label>
<input class="btn btn-lg btn-login btn-block" type="submit" value="Submit"/>
<div class="registration">
Already Registered.
<a class="" href="login.html">
Login
</a>
</div>
</div>
</form>
I'm starting now with Django, I read the documentation about custom forms, but I didn't find nothing about how to validate fields as forms.as_p does.
That is the wrong way to produce custom HTML for your form. You should still use the Django form fields - {{ form.first_name }} etc - rather than creating HTML versions yourself and populating them.
However, the issue is simpler than that: you have forgotten to add the {{ form.myfield.errors }} for each field, and the {{ form.non_field_errors }} at the top of the form.
Also note there's no reason to do all that extra work in save. All of those fields are already being set by the superclass: the only thing you need to take care of manually is user.set_password.

Categories