I am always getting none from request.POST.get in django - django

nam and mob field are userinput fields which i am using for user input and later i am using them for filtering
{% block content %}
<form class="form-signin" action="" method="POST">
{% csrf_token %}
<div class="mb-3">
<input type="text" name="nam" id="nam" class="form-control-sm center-block" placeholder="Nam" autofocus>
</div>
</div>
<div class="mb-3">
<select class="custom-select center-block" name="mob" id="mob" >
<option>{{ customer.sponsor }}</option>
{% for i in sponsor %}
<option value="{{ i.mobile }}"> {{ i.mobile|add:' - '|add:i.name }} </option>
{% endfor %}
</select>
<div class="invalid-feedback">
Please select a valid Existing Customer.
</div>
</div>
<div class="mb-3">
Search
Urls.py
path('customer_view',views.customer_view,name='customer_view')
Views.py
def customer_view(request):
print(request.method )
name1 = str(request.POST.get('nam'))
print(name1)
mobile1 = str(request.POST.get('mob'))
print(mobile1)
customers_list = customer.objects.filter(
mobile=mobile1) & customer.objects.filter(name=name1)
sponsors = customer.objects.all().distinct('mobile')
ctx = { 'customer': customers_list, 'sponsor': sponsors }
return render(request, 'pages/customer_view.html', ctx)

You use href which does not submit the form. You need a submit button and change your action of your form to your view url. Try this:
{% block content %}
<form class="form-signin" action="{% url 'customer_view' %}" method="POST">
{% csrf_token %}
<div class="mb-3">
<input type="text" name="nam" id="nam" class="form-control-sm center-block" placeholder="Nam" autofocus>
</div>
</div>
<div class="mb-3">
<select class="custom-select center-block" name="mob" id="mob" >
<option>{{ customer.sponsor }}</option>
{% for i in sponsor %}
<option value="{{ i.mobile }}"> {{ i.mobile|add:' - '|add:i.name }} </option>
{% endfor %}
</select>
<div class="invalid-feedback">
Please select a valid Existing Customer.
</div>
</div>
<div class="mb-3">
<input type="submit" value="Search"/>
.
.
...

In your form, you write a button as:
Search
But this thus means that this is just a link that links to a new page. As a result, the browser will make an (empty) GET request to the given url, and never submit the form.
You can construct a button that submits the form with:
<form class="form-signin" action="{% url 'customer_view' %}" method="post">
<!-- … -->
<button type="submit" class="btn btn-primary btn-sm" role="button">Search</button>
<!-- … -->
</form>
That being said, a search is often done with a GET request, so you might want to change method="get", and obtain the parameters through request.GET.get(..) instead.

Related

django-bootstrap5 and button alignment

I want to display a button next to a form instead of below:
This is how it looks:
should look like this:
corresponding code:
form:
class TheForm(forms.Form):
var = forms.ChoiceField(choices = choices, label = "")
temp
late:
{% if TheForm %}
<form method = "post">
{% csrf_token %}
{% bootstrap_form TheForm %}
{% bootstrap_button button_type="submit" content="OK" %}
</form>
{% endif %}
EDIT:
Got it working, but the code only works with one input field:
I imagined it would look like this:
but the produced code looks weird too:
<form method="POST" action="/singleDevice">
<input type="hidden" name="csrfmiddlewaretoken" value="...">
<div class="row">
<div class="col-9">
<div class="col-12">
<select name="env" class="form-select" id="id_env">
<option value="0">A</option>
<option value="3">NB</option>
</select>
</div>
<div class="col-12">
<label class="visually-hidden" for="id_Number">directly enter a number</label>
<input type="text" name="Number" class="form-control" placeholder="directly enter a number" id="id_Number">
</div>
</div>
<div class="col-3">
<button class="btn btn-primary" type="submit">OK</button>
</div>
</div>
</form>
Try bootstrap Grid system,
template.html
{% if TheForm %}
<form method = "post">
{% csrf_token %}
<div class="row"> <!-- creates a row of 12 parts -->
<div class="col-lg-9"> <!-- Creates a column with width of 9 parts out of the above 12 parts -->
{% bootstrap_form TheForm %}
</div>
<div class="col-lg-3"> <!-- Creates a column with width of remaining 3 parts out of the above 12 parts -->
{% bootstrap_button button_type="submit" content="OK" %}
</div>
</div>
</form>
{% endif %}
EDIT: CSS TO SET BUTTON AT THE END OF FORM
<form method="POST" action="/singleDevice">
<input type="hidden" name="csrfmiddlewaretoken" value="...">
<div class="row">
<div class="col-9">
<div class="col-12">
<select name="env" class="form-select" id="id_env">
<option value="0">PROD</option>
<option value="1">QA</option>
<option value="2">DEV</option>
<option value="3">NB</option>
</select>
</div>
<div class="col-12">
<label class="visually-hidden" for="id_Number">directly enter a number</label>
<input type="text" name="Number" class="form-control" placeholder="directly enter a number" id="id_Number">
</div>
</div>
<div class="col-3">
<button class="btn btn-primary form-submit-button" type="submit">OK</button>
</div>
</div>
</form>
base.css:
.form-submit-button{
display: inline-block;
margin-top: 95%; /* (approx) */
}
CHANGES: I have set a classname to the submit button and pushed the submit button to the bottom end of the y-axis using margin-top (percentage ensures that it stays below even on resizing)

Django: Trouble with logging user using Bootstrap login.html

I'm using Django 3.0.2 + Boostrap. I have created a registration/login.html page. The contents of this page are shown below.
The page renders correctly and most of it works OK. However, I am unable to login to my website through this page. I keep getting Your username and password did not match. Please try again. I can login to the admin website without any issues if I use the same username/password. I am not sure what is wrong with my login.html. Any ideas?
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password did not match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account does nohave access to this page. To proceed,please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
</div>
<form class="user" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control form-control-user" id="exampleInputUserName" placeholder="Username">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user" id="exampleInputPassword" placeholder="Password">
</div>
<input type="submit" class="btn btn-primary btn-user btn-block" value="Login">
<input type="hidden" name="next" value="{{ next }}">
</form>
<hr>
<div class="text-center">
<a class="small" href="forgot-password.html">Forgot Password?</a>
</div>
<div class="text-center">
<a class="small" href="register.html">Create an Account!</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Contents of views.py:
from django.contrib.auth import logout
def logout_view(request):
"""Log out user from the website."""
logout(request)
Your input types are missing the name attribute. As per the Mozilla docs:
A string specifying a name for the input control. This name is
submitted along with the control's value when the form data is
submitted.
So the name is submitted with the form. But what if there is no name attribute?
Same Documentation explains:
Consider the name a required attribute (even though it's not). If an
input has no name specified, or name is empty, the input's value is
not submitted with the form.
So your username and password are not sent to the backend.
You need to provide the name attributes to your input types.
<form class="user" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control form-control-user" id="exampleInputUserName" placeholder="Username" `name="username"`>
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user" id="exampleInputPassword" placeholder="Password" name="password">
</div>
<input type="submit" class="btn btn-primary btn-user btn-block" value="Login">
<input type="hidden" name="next" value="{{ next }}">
</form>
It is front-end issue, not particularly related to Django.

Ajax call from a dropdown to open a new page is not working

I have a form where there are 3 fields and i want to insert them into databse. My table is kitty_member and fields are code, slot and customer. code belongs to primary key of kitty table which is having a field "totalmembers". As user selects "code". i want to show the list of intigers from 1 to "totalmembers" wrt to "code". For example when totalmembers = 100 for code = 'K00001' the in slots dropdown 1 to 100 should show and if code = 'k00002' which is having totalmembers = 50 then 1 to 50 should show on the dropdown.So i have written one ajax on the "code" field. I am trying to call an url by passing paramter "code". So that i can able to return the "totalmembers" to populate the dropdown "Slots". Ajax call is below which is in base.html.
<script>
function callsamepage() {
var code1 = $('#code').val()
console.log(code)
$.ajax({
type:"POST",
url: "kitty_member1" ,
data:{
code: code1
},
success: function(result){
console.log('correct',result)
}
});
}
Views.py
def kitty_member1(request,code='None'):
url_name = request.resolver_match.url_name
print(url_name)
print(code)
customers = customer.objects.all().distinct('mobile')
kittys = kitty.objects.all()
if code != 'None' :
kittys = kittys.filter(code=code)
for i in kittys:
totalmembers = i.totalmembers
members = []
for j in range(totalmembers):
members.append(j)
print(members)
ctx = {'customer': customers, 'kitty': kittys, 'member':members}
else:
ctx = {'customer': customers, 'kitty': kittys}
Urls.py
urlpatterns = [
path('',views.index,name='index'),
path('kitty_member',views.kitty_member_save,name='kitty_member'),
path('kitty_member1/', views.kitty_member1, name='kitty_member1'),
path('kitty_member1/<code>', views.kitty_member1, name='kitty_member1')]
template
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="container">
<div class='row'>
<div class="col-lg-12 col-xs-12">
<div class="customer">
<form name='myform' class="form-signin" action="" method="POST">
{% csrf_token %}
<h1 class="h3 mb-3 font-weight-normal redc">Kitty Slots Allocation to Customer</h1>
<div class="mb-3">
<select class="custom-select center-block" name="code" id="code" required onchange="callsamepage()">
<option value="">Select Kitty</option>
{% for i in kitty %}
<option value="{{ i.code }}" > {{ i.code|add:' - '|add:i.name }} </option>
{% endfor %}
</select>
<div class="invalid-feedback">
Please select a valid Existing Customer.
</div>
</div>
<div class="mb-3">
<select class="custom-select center-block" name="slot" id="slot" required >
{% for j in member %}
<option value="{{ j }}" > {{ j }} </option>
{% endfor %}
</select>
<div class="invalid-feedback">
Please select a valid Slot.
</div>
</div>
<div class="mb-3">
<select class="custom-select center-block" name="customer" id="customer" required>
<option value=""> Select Customer </option>
{% for i in customer %}
<option value="{{ i.mobile }}"> {{ i.mobile|add:' - '|add:i.name }} </option>
{% endfor %}
</select>
<div class="invalid-feedback">
Please select a valid Existing Customer.
</div>
</div>
<div style="padding-top: 20px;">
{% if request.resolver_match.url_name == 'kitty_member' %}
<button class="btn btn-md btn-primary" type="submit" data-toggle="modal"
data-target="#exampleModalCenter">Save</button>
{% endif %}
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
I am not able to populate the "Slot" field.
You can write a api code like this in views.py:
from django.http import JsonResponse
def code_api(request):
code = request.GET.get('code', None)
kitty_obj = kitty.objects.filter(code=code).first()
total_me = mbers = 0
if kitty_obj:
total_members = kitty_obj.totalmembers
return JsonResponse({"total_members": total_members})
and add an url in urls.py like that
path('kitty_member1/code_api/', views.code_api, name='code_api'),
and add a jquery in template
$(document).ready(function(){
$('#code').on('change', function() {
$('#slot').children().remove();
var code = this.value;
$.get("{% url 'code_api'%}?code="+code, function(data, status){
var total_members = data['total_members'];
for(int i=1;i<=parseInt(total_members);i++){
$("#slot").append("<option value='"+i+"'>"+i+"</option>'");
}
});
});
});

2 similar views and templates but only one template shows form options

I'm really stuck on this one. I have a working view/template that has a form select option that populates options from my model
views.py
def random(request):
classroom = Classroom.objects.filter(teacher=request.user).order_by('course_block')
classblock = request.GET.get('class_block')
students = Student.objects.all().filter(classroom__course_block=classblock)
nicknames = [s.nickname for s in students]
data = serializers.serialize("json", students, fields = ("nickname", "attend"))
student_names = json.dumps(list(nicknames))
context = {'students': students}
context['classroom'] = classroom
context['student_names'] = student_names
context['data'] = data
template = loader.get_template('randomizer/randomize.html')
print (data)
return render(request, 'randomizer/randomize.html', context)
ramdomize template
{% extends 'randomizer/base.html' %}
{% load static %}
{% block body %}
<div id="djangorandom">
{{ classroom.id }}
<form action="{% url 'randomizer:random' %}" method="get">
{% csrf_token %}
<div class="form-group">
<select class="form-control" name="class_block">
{% for room in classroom %}
<option value={{ room.course_block }}>{{ room.get_course_block_display }}</option>
{% endfor %}
</select>
</div>
<span><input class="btn btn-default" type="submit" value="Submit"></span>
</form>
</div>
Page source returns:
<div class="form-group">
<select class="form-control" name="class_block">
<option value=11>Block 1-1</option>
<option value=13>Block 1-3</option>
<option value=14>Block 1-4</option>
<option value=P13>Pair 1-3</option>
</select>
</div>
Now I've copied a lot of this code for a slightly different template and purpose:
def pair(request):
classroom = Classroom.objects.filter(teacher=request.user).order_by('course_block')
classblock = request.GET.get('class_block')
students = Student.objects.all().filter(classroom__course_block=classblock)
nicknames = [s.nickname for s in students]
data = serializers.serialize("json", students, fields = ("nickname", "attend"))
student_names = json.dumps(list(nicknames))
context= {'classroom': classroom}
context['students'] = students
context['student_names'] = student_names
context['data'] = data
template = loader.get_template('randomizer/pairing.html')
print(data)
return render(request, 'randomizer/pairing.html')
{% extends 'randomizer/base.html' %}
{% load static %}
{% block body %}
<div id="djangorandom">
{{ classroom.id }}
<form action="{% url 'randomizer:pair' %}" method="get">
{% csrf_token %}
<div class="form-group">
<select class="form-control" name="class_block">
{% for room in classroom %}
<option value={{ room.course_block }}>{{ room.get_course_block_display }}</option>
{% endfor %}
</select>
</div>
<span><input class="btn btn-default" type="submit" value="Submit"></span>
</form>
</div>
But the page source doesn't show any of the options for the form selects:
<form action="/randomizer/pairing/" method="get">
<input type='hidden' name='csrfmiddlewaretoken' value='ADVUsnTserljrnDvRlmeTPyvjMOzva5xj7t8LSeDmPxnkBUtx4XmfXAI5aRfJky6' />
<div class="form-group">
<select class="form-control" name="class_block">
</select>
</div>
<span><input class="btn btn-default" type="submit" value="Submit"></span>
</form>
I've practically copied everything from the first view/template to the second view/template. I wondered if there was a scope issue where def pair re-uses the code from def random, but I commented out def random and that didn't help.
Your second view doesn't pass the context into the render() call, so there is no classroom variable and nothing to iterate over in the template.
(Note, in both views the template = loader.get_template(...) call is irrelevant and not used; you should remove those lines.)

Django: Redirect Change Password URL

I have the following two URLs:
url(r'^change-password/$',django.contrib.auth.views.password_change,{'template_name': 'meta/changepassword.html', 'post_change_redirect': '/password-changed/'},name='change_password'),
url(r'^change-passwordiOS/$',django.contrib.auth.views.password_change,{'template_name': 'meta/changepassword.html', 'post_change_redirect': '/password-changed/'},name='change_passwordiOS'),
I thought if I used the following within the change password form it would override what URL would be loaded:
{% if 'iOS' in request.path %}
<input type="hidden" name="next" value="/profileiOS/" />
{% endif %}
But when I reach the change password from the url(r'^change-passwordiOS/$' and click the "Change Button" it does not goto the /profileiOS/ as expected but the standard /profile/ URL.
Any help would be appreciated.
/change-password/ view:
#login_required
def password_changed(request):
messages.success(request, 'Your password has been changed.')
return redirect(reverse('profile'))
Full Change Password Form:
<form class="form-horizontal" role="form" method="post" action="">
{% csrf_token %}
<fieldset>
<div class="form-group">
<label class="col-md-6 control-label">{{ form.old_password.label }}:</label>
<div class="col-md-6">
<input name="old_password" type="password" class="form-control"/>
<div class="text-danger">
{% for error in form.old_password.errors %}{{ error }}<br/>{% endfor %}
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-6 control-label">{{ form.new_password1.label }}:</label>
<div class="col-md-6">
<input name="new_password1" type="password" class="form-control"/>
<div class="text-danger">
{% for error in form.new_password1.errors %}{{ error }}<br/>{% endfor %}
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-6 control-label">{{ form.new_password2.label }}:</label>
<div class="col-md-6">
<input name="new_password2" type="password" class="form-control"/>
<div class="text-danger">
{% for error in form.new_password2.errors %}{{ error }}<br/>{% endfor %}
</div>
</div>
</div>
<div class="form-group">
<div class="text-right col-sm-12">
<button type="submit" class="btn btn-primary">Change Password^</button>
</div>
</div>
</fieldset>
{% if 'iOS' in request.path %}
<input type="hidden" name="next" value="/profileiOS/" />
{% endif %}
</form>
You are manually redirecting to /profile/ in password_changed view. You can change your redirect logic to depend on post param from template:
#login_required
def password_changed(request):
messages.success(request, 'Your password has been changed.')
return redirect(request.POST.get('next', reverse('profile')))