form data not sent to view as post - django

Hi I have a two forms on my home page, a `contact us' form and a 'drop down form to change the language of the site. since both forms are going to be in the base template i figure i must find a way to send the content of the forms to specific views to process the submission. Currently my site is a single page site so i dont have a problem with the contact form
Contact Form is
<form method="post" action="" role="form" id="footer-form">
{% csrf_token %}
<div class="form-group has-feedback">
<label class="sr-only" for="{{ form.name.label }}">{{ form.name.label }}</label>
{{ form.name }}
<p class="help-block danger">{{ form.name.errors }}</p>
<i class="fa fa-user form-control-feedback"></i>
</div>
<div class="form-group has-feedback">
<label class="sr-only" for="{{ form.email.label }}">{{ form.email.label }}</label>
{{ form.email }}
<p class="help-block danger">{{ form.email.errors }}</p>
<i class="fa fa-envelope form-control-feedback"></i>
</div>
<div class="form-group has-feedback">
<label class="sr-only" for="{{ form.message.label }}">{{ form.message.label }}</label>
{{ form.message }}
<p class="help-block danger">{{ form.message.errors }}</p>
<i class="fa fa-pencil form-control-feedback"></i>
</div>
<input type="submit" value="Send" class="btn btn-default">
</form>
And the language form is
<form action="/setlang" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="/"/>
<select name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"
{% if language.code == LANGUAGE_CODE %}
selected="selected"{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input type="submit" value="Go"/>
</form>
View that renders page
#csrf_exempt
def home(request):
# send_email(['elraphah#gmail.com'],'YonniQ','info#verdin.no',"Testing","Thanks for the Test" )
form = ContactForm()
if request.method=='POST':
form = ContactForm(request.POST)
print 'Form Validation '
print form.is_valid()
if form.is_valid():
send_email(['info#verdin.no'], request.POST['name'], request.POST['email'], request.POST['message'])
return render_to_response('home.html',locals())
Due to some issues i was having with django's i18n's set_language view i decided to create my own hence setlang in my form action.
When i make the action attrib empty like in the contact form, and submit, the form submits to my home view and the queryDict contains the form fields and values but when i attempt to submit to another view, in this case through /setlang url the form does not post, i only get and empty queryDict. I dont know why this is the case.

Try using url tag (https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#url), you must have two urls defined in your urls.py, so in each action form attribute place the correct view name using tag, something like:
For contact form:
action={% url 'home' %} # url(r'^/$', views.home, name='home')
For setlang form:
action={% url 'setlang' %} # url(r'^/setlang$', views.set_lang, name='setlang')
Then in each function view you can filter the request by post method, as you did in home view.
Hope it can help.

Related

Customized django all-auth form not submitting

I am using the django all-auth login form. I wanted to customize the look of the form fields so I changed login.html within the account folder to look like this:
<form class="login" method="POST" action="{% url 'account_login' %}">
{% csrf_token %}
{% for field in form.visible_fields|slice:'2' %}
<div class="row form-group">
{% if field.name == 'login' %}
<input type="text" placeholder="Email"><i class="fas fa-at"></i>
{% else %}
<input type="password" placeholder="Password"><i class="la la-lock"></i>
{% endif %}
</div>
{% endfor %}
Forgot Password?
<button type="submit">Sign In</button>
</form>
The form renders exactly how I would like it to, however nothing happens when I click on submit. What is strange to me is that the form submits perfectly fine if in place of my for loop I simply type {{ form.as_p }}, it just doesn't look how I want. Can anyone see an error in my loop, or is there something else wrong here. I have been looking for a solution online but so far been unsuccessful
You need to specify the names of the fields in your input tags otherwise the POST dictionary will be empty. You are using {% if field.name == 'login' %} but you forgot to specify the name attribute. Same applies for the password input.
<form class="login" method="POST" action="{% url 'account_login' %}">
{% csrf_token %}
{% for field in form.visible_fields|slice:'2' %}
<div class="row form-group">
{% if field.name == 'login' %}
<input name='login' type="text" placeholder="Email"><i class="fas fa-at"></i>
{% else %}
<input name='password' type="password" placeholder="Password"><i class="la la-lock"></i>
{% endif %}
</div>
{% endfor %}
Forgot Password?
<button type="submit">Sign In</button>
</form>

Django - Account Settings BooleanField

I reviewed most of the posts here related to Django and BooleanField update, but I couldn't find any related to my problem solution.
I have a custom user models.py:
# Own custom user model
class Account(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
guardianSource = models.BooleanField(default=True)
bbcSource = models.BooleanField(default=False)
independentSource = models.BooleanField(default=False)
categoryCoronaVirus = models.BooleanField(default=False)
categoryPolitics = models.BooleanField(default=False)
categorySport = models.BooleanField(default=False)
When I register a user it seems to register in the database all correct values for the checkboxes. The problem is when I want to edit user information I cannot see if a checkbox was checked on registering or not, it displays the checkboxes itself, but they are all empty (False). However, it correctly requests the username and displays it so I can edit it, but all the checkboxes are unchecked.
views.py:
def account_view(request):
if not request.user.is_authenticated:
return redirect('login')
context = {}
if request.POST:
form = AccountUpdateForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
context['success_message'] = "Updated"
else: # Display the saved user details from database
form = AccountUpdateForm(
initial = {
'username':request.user.username,
"guardianSource": request.user.guardianSource,
"bbcSource": request.user.bbcSource,
"independentSource": request.user.independentSource,
"categoryCoronaVirus": request.user.categoryCoronaVirus,
"categoryPolitics": request.user.categoryPolitics,
"categorySport": request.user.categorySport,
})
context['account_form'] = form
return render(request, 'accounts/account.html', context)
account html:
{% extends 'base.html' %}
{% block content %}
<form class="form-signin" method="POST">{% csrf_token %}
<h1 class="h3 mb-3 font-weight-normal">Account Settings</h1>
<label for="username" class="sr-only">Username</label>
<input type="text" name="username" id="username" class="form-control" placeholder="Username" value="{{account_form.initial.username}}">
<br>
<div class="form-control">
<p><b>Please choose news sources!</b></p>
<label for="guardianSource" >The Guardian</label>
<input type="checkbox" name="guardianSource" id="guardianSource" value="{{account_form.initial.guardianSource}}" >
<br>
<label for="bbcSource" >BBC News</label>
<input type="checkbox" name="bbcSource" id="bbcSource" value="{{account_form.initial.bbcSource}}" >
<br>
<label for="independentSource" >The Independent</label>
<input type="checkbox" name="independentSource" id="independentSource" value="{{account_form.initial.independentSource}}" >
</div>
<br>
<div class="form-control">
<p><b>Please choose news category!</b></p>
<label for="categoryCoronaVirus" >The Guardian</label>
<input type="checkbox" name="categoryCoronaVirus" id="categoryCoronaVirus" value="{{account_form.initial.categoryCoronaVirus}}" >
<br>
<label for="categoryPolitics" >BBC News</label>
<input type="checkbox" name="categoryPolitics" id="categoryPolitics" value="{{account_form.initial.categoryPolitics}}" >
<br>
<label for="categorySport" >The Independent</label>
<input type="checkbox" name="categorySport" id="categorySport" value="{{account_form.initial.categorySport}}">
</div>
{% for field in registration_form %}
<p>
{% for error in field.errors %}
<p sttle="color:red"> {{ error }}</p>
{% endfor %}
</p>
{% endfor %}
{% if registration_form.non_field_errors %}
<div style="color:red;">
<p>{{registration_form.non_field_errors}}</p>
</div>
{% endif %}
{% for field in account_form %}
<p>
{% for error in field.errors %}
<p sttle="color:red"> {{ error }}</p>
{% endfor %}
</p>
{% endfor %}
{% if account_form.non_field_errors %}
<div style="color:red;">
<p>{{account_form.non_field_errors}}</p>
</div>
{% endif %}
{% if success_message %}
<p style = "color: green; text-align:center;">{{success_message}}</p>
{% endif %}
<h6 class="text-muted">
If you don't choose a source and category it will automatically assign the ones that are checked!<br>
NOTE: You <b>MUST</b> select at least 1 choice for each!!!
</h6>
<button class="btn btn-lg btn-primary btn-block" type="submit">Save Changes</button>
</form>
<div class="d-flex flex-column">
<a class="m-auto" href="{% url 'password_change' %}">Change password</a>
</div>
{% endblock content %}
Thanks in advance and I am sorry if my post is duplicated.
EDIT:
The issue was found.
In the account.html file the values for each input type checkbox were wrong.
What I changed from:
<input type="checkbox" name="guardianSource" id="guardianSource" value="{{account_form.initial.guardianSource}}" >
To:
<input type="checkbox" name="guardianSource" id="guardianSource" value="{{account_form.guardianSource}}" >
For all the input values after the username input the initial had to be removed
You don't need to pass initial when you are initializing a ModelForm and have the instance
else: # Display the saved user details from database
form = AccountUpdateForm(instance=request.user)
You can use the field directly in the template and it will be rendered with the correct values, you don't need to construct the html for the input yourself
<label for="{{ account_form.guardianSource.id_for_label }}">The Guardian</label>
{{ account_form.guardianSource }}
The docs have a section on how to render fields manually

I am always getting none from request.POST.get in 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.

Django next page in pagination on form submission

def listing(request):
contact_list = Question.objects.all()
paginator = Paginator(contact_list, 1) # Show 25 contacts per page
page = request.GET.get('page')
contacts = paginator.get_page(page)
Let's say in each page I have a form, and when the form submitted I need to go to the next page.
I first tried to add a hidden field in the form, and manually calculate the next page, and put into HTTPResponseRedirect, but then I get an empty object error for the last page because of the following:
<input type="hidden" name="next" value="?page={{ contacts.next_page_number }}">
That page contains no results
{% for contact in contacts %}
{# Each "contact" is a Contact model object. #}
{{ contact.question_text|upper }}<br>
...
<form action="{% url 'listing' %}" method="post">
{% csrf_token %}
{% for choice in contact.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
<input type="hidden" name="next" value="?page={{ contacts.next_page_number }}">
{% endfor %}
<input type="submit" value="Vote">
</form>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>
{% if contacts.has_next %}
next
last »
{% endif %}
</span>
</div>
So what should be my strategy? Do I need to create a seperate view for form action, or should I use listing as form action and check wheter it is a GET/POST method, I am kind of lost here.

django form wizard, does not go to second step

I am trying to perform the following using Django :
Wizard containing two formds
First form is a simple form containing some Ajax to compute automatically some fields
Second form is a user registration
The problem is the following :
The first form is displayed correctly and the Ajax within the page is working fine
The second form is never displayed after pushing on the button "submit"
The code is as follows :
urls.py
from forms import InsertPropertyForm1, InsertPropertyForm2
from views import InsertPropertyWizard
urlpatterns = patterns('',
url(r'^addProperty/$', InsertPropertyWizard.as_view([InsertPropertyForm1, InsertPropertyForm2]), name='addProperty'),
)
views.py
FORMS = [("property", InsertPropertyForm1),
("test", InsertPropertyForm2)
]
TEMPLATES = {'0': 'realEstate/addProperty.html',
'1' : 'realEstate/test.html',
}
class InsertPropertyWizard(SessionWizardView):
def get_template_names(self):
print ("next step !!!!! " + str(self.steps.current))
return [TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
print "Wizard done"
#do_something_with_the_form_data(form_list)
return HttpResponseRedirect('http://TO_FILL_IN')
realEstate/addProperty.html
{% extends 'realEstate/base.html' %}
{% load socialaccount %}
{% load i18n %}
{% block head %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<h1> Insert an ad </h1>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form class="form-horizontal" role="form" action="" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
</table>
{{ form.non_field_errors }}
<fieldset>
<legend>Localisation</legend>
<div class="form-group">
{{ form.country.errors }}
<label class="col-lg-1" for="id_country">{{form.country.label}}</label>
<div class="col-lg-1">
{{ form.country }}
</div>
</div>
</fieldset>
</fieldset>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans "first step" %}
</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "prev step" %}
</button>
{% endif %}
<input type="submit" value="{% trans "submit" %}"/>
</form>
{% endblock %}
Just thought it could help someone.
Problem was that one of the field was not defined in the form and I forgot to include it in the template.
The behaviour of the wizard was correct. It got stuc on the first page but did not display the error on the screen as the field was not displayed.
Got me crazy but it was my fault.
Cheers