Django 1.8 handwritten form no POST data - django

I've become very frustrated by a problem I'm having. I have a large form that's hand-written (not using Django's forms), and am simply trying to access the data from the inputs in the views (in that case, some inputs were posting, others weren't).
Leaving the specifics of that form aside for now since there are too many things at play, in my troubleshooting process I wrote the simplest form I could think of, and am now getting no POST data besides the csrf_token.
I have no idea why this would be, since something similar (and much more complex) works fine on several other django projects I'm running. For this example, I tried with action="" as well to no avail. Is there something incredibly obvious I'm missing?
Here's the html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="POST" id="theForm" action="/simpleForm/">{% csrf_token %}
<input type="text" id="theText" value="Where am I?" />
<input type="hidden" id="hiddenInput" value="I don't exist" />
<input type="submit" />
</form>
</body>
</html>
Here is a simple view checking for data:
from django.shortcuts import render
def simpleForm(request):
if (request.method == 'POST'):
print('In post')
print(request.POST)
for i in request.POST.keys():
print('key: {0} value: {1}'.format(i, request.POST[i]))
return render(request, 'simpleForm.html')
else:
return render(request, 'simpleForm.html')

You're missing the 'name' attribute of the tags in your HTML form. Without those, Django will not add them to request.POST
<form method="POST" id="theForm" action="/simpleForm/">{% csrf_token %}
<input type="text" id="theText" name="mytext" value="Where am I?" />
<input type="hidden" id="hiddenInput" name="myhidden" value="I don't exist" />
<input type="submit" />

Related

Send JSON from Places Autocomplete to Flask

I'm working on my very first web app utilizing the Google Places Autocomplete functionality in the frontend and Flask in the backend.
Current situation:
Whenever an address is selected from the autocomplete suggestions, a variable called 'address' is populated in the background containing the API response as JSON. Using a window alert I can confirm that this part works fine.
To-Do/ issue:
The address variable should be sent over to Flask so that I can do use it going forward.
Using AJAX to post the data however it never seems to reach Flask. The output is always None.
My best guess is that the submit button implemented after the Autocomplete stuff somehow overrides the JSON POST data in order to keep only the actual text which is in the form while submitting*.
Does that make sense? If yes, how can I still send the JSON data successfully? Or is the issue somewhere else?
I would appreciate any help.
Here is my code:
home.html
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
{% from "_formhelpers.html" import render_field %}
<div class="container">
<form class="form form-horizontal" action="" method="post" role="form" novalidate>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=key&libraries=places&language=en"></script>
<script type="text/javascript">
google.maps.event.addDomListener(window, 'load', function () {
var autocomplete = new google.maps.places.Autocomplete(document.getElementById('autocomplete'),{
types: ['geocode']
});
// autocomplete.setFields('address_components');
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace();
var address = place.address_components;
window.alert(JSON.stringify(address));
}
)})
$.ajax({
type: "POST",
url: "/",
data: address,
success: function(){},
dataType: "json",
contentType : "application/json"
});
</script>
<input type="text" id="autocomplete" size=50 style="width: 250px" placeholder="Enter your location" name=inputkiez>
<a href=# id=autocomplete><button class='btn btn-default'>Submit</button></a>
</form>
<div class="row">
or check out <a href='/result'> the latest reviews from others </a>
<div>
</div>
{% endblock %}
routes.py
#app.route('/', methods=['GET','POST'])
def search():
if request.method == 'POST':
jsdata = request.get_json()
flash('Data is: {}'.format(jsdata))
return redirect('/review')
return render_template('home.html')
#app.route('/review', methods=['GET', 'POST'])
def review():
reviewform = ReviewForm()
if reviewform.validate_on_submit():
userreview = Reviews(
reviewcriteria1= reviewform.reviewcriteria1.data,
reviewcriteria2= reviewform.reviewcriteria2.data,
reviewcriteria3= reviewform.reviewcriteria3.data,
)
db.session.add(userreview)
db.session.commit()
return redirect('/result')
return render_template('review.html', form=reviewform)
*The text in the form would include the address selected from Autocomplete but without any additional data obviously. I even managed to pass this text to the next page with request.form.to_dict() but this is not good enough for my use case since I also want at least the postal code to be sent over.
This is not the exact answer to my question but I found a way to send over the data to flask without having to bring in JSON/AJAX at all.
The trick is to send the data from the Autoplaces response as a hidden input of the form:
<form method="post" action="">
<input id="userinput" placeholder="Enter a location" type="text" name="name" class="form-control"><br>
<div id="map" style="height: 300px;width: 300px; float: none; margin: 0 auto;"></div><br>
<input type="hidden" name="address" id="address">
<input type="submit" name="submit" value="Submit" class="form-control btn btn-primary">
<div>or check out <a href='/result'> the latest reviews from others </a></div>
</form>
Then in routes.py you can easily get the data like this:
#app.route('/', methods=['GET','POST'])
def search():
if request.method == 'POST':
address = request.form['address']
# do something
This is basically a slightly modified version of the solution posted here (YT video).

django parameter via get not working while forming direct url

Base URL:
path('api/product/',
include(('store.urls', 'store'),
namespace='api-product')),
Store URL:
path('invoice-pdf-get/',
invoice.InvoiceToPdf.as_view(),
name='invoice-pdf-get'),
HTML:
<html>
<body>
<form method="get" action="{% url 'api-product:invoice-pdf-get' %}?R={{ invoice.invoice_unique_number }}">
<input type="submit" value="Generate PDF">
</form>
</body>
</html>
When I hit the button, I get the url in browser as:
http://localhost:8000/api/product/invoice-pdf-get/?
Where as expecting:
http://localhost:8000/api/product/invoice-pdf-get/?invoice_number=SOMEKEY
Though if I submit a hidden type input via form, I get the expected result but I was reading: Daniel Roseman SO answer. to pass parameter via GET.
Though inspect shows the URL (see image) but why am I not getting expected result?
When a form is submitted via GET, the values in the form are sent as the querystring. This overrides any querystring in the action URL. See this SO answer for example.
You should put your value as a hidden input in the form itself.
<form method="get" action="{% url 'api-product:invoice-pdf-get' %}">
<input type="hidden" name="R" value="{{ invoice.invoice_unique_number }}">
<input type="submit" value="Generate PDF">
</form>

How can I access data sent in a post request in Django?

I have a form that is supposed to create a new 'Quote' record in Django. A 'Quote' requires a BookID for a foreign key.
This is my form
<form method="POST" action="{% url 'quotes:createQuote' %}">
{% csrf_token %}
<section>
<label for="q_text">Quote Text</label>
<input type="text" name="text" id="q_text" placeholder="Enter a Quote" style="padding-left:3px"> <br>
<label for="q_book">Book ID</label>
<input type="text" name="bookID" id="q_book" placeholder="Enter Book ID" style="padding-left:3px"> <br>
<label for="q_disp">Display Quote Now?</label>
<input type="radio" name="display" id="q_disp" value="True"> True
<input type="radio" name="display" value ="False">False <br>
<button value="submit">Submit</button>
</section>
</form>
And this is the method that it is targeting
def createQuote(request):
#b = get_object_or_404(Book, pk=request.bookID)
return HttpResponseRedirect(reverse('quotes:index'))
Somewhere in that request argument I assume there is some sort of field that contains the bookID the user will pass in on the form. How do I get at that information?
Bonus points for anyone who can tell me some way I can visualise data like I might with console.log(some.collection) in Javascript
if request.method == "POST":
book_id = request.POST['book_id']
Assuming you're sure it's in there. Otherwise you'll need to verify/provide a default value like you would for a normal python dictionary.
As for visualising the data, do you mean printing it to the console? In which case if you're running the django runserver you can just do print some_data. If you want it formatted a little nicer, you can use pretty print:
import pprint
pp = pprint.PrettyPrinter()
pp.pprint(some_data)

Django Form Submission Error

I have this recurring problem with form submission in Django, and the frustrating part is that I'm not sure how to interpret what's happening. Essentially I have different pages with form submissions on them. Some of them work as following
localhost/page/formpage--> localhost/page/receivingpage
which is what I expect. Othertimes, it goes to a page like this
localhost/page/formpage--> localhost/page/formpage/recevingpage
and the screen shows a blank form page, which is not what I expect. I'm not sure how to interpret this, and I'm not sure where to look for errors in my code. I think I don't fully understand what's going on when I submit a form, how does it generate a URL after I press 'submit'?
Edit: here is my html form:
<!DOCTYPE HTML>
<html>
<div>
<p>Entry Form</p>
<form action= "user" method="post" >
{% csrf_token %}
<p><label for="id_username">Username:</label>
<input id="id_username" type="text" name="username"" /></p>
<p><label for="id_password">Password</label>
<input type="password" name="password" id="id_password" /></p>
<input type="submit" value="Submit" />
</form>
</div>
</html>
I suspect it isn't the form, I have it on another application and it works... the trouble is I don't know if it's the view, the template, or w/e, so I'll update the post with info as people request it.
I'd recommend putting in an action using the url template tag. With that, you will know for certain where the form is going to end up:
<form action="{% url 'user-url-name' %}" method="post">
The url tag will be an absolute url. Without this, you're going to end up at a relative url depending on where in your application the user submits the form, which can be quite confusing during development and not entirely correct.
Using {% url %} tag is the proper way to do. Your problem can also be solved by adding a forward slash / to the action attribute like this:
<form action="/user" method="post" >
Hope this helps!

How to properly use the django built-in login view

I'm just getting started with Django, and I'm trying to use built-in features as much as possible. As such, for user login, I'm using the built-in login view, and assigning it to the base url of my site:
urlpatterns=patterns('django.contrib.auth.views',
url(r'^/$','login',{'template':'mytemplate.html'}),
mytemplate.html looks something like this:
<!DOCTYPE html>
<html>
<body>
{%if form.errors %}
<p> Invalid username/password combination, please try again </p>
{% endif %}
<h1>Welcome to My Site!</h1>
<form action="{% url django.contrib.auth.views.login %}" method="post">
{% csrf_token %}
{{form.username.label_tag}}{{form.username}}
{{form.password.label_tag}}{{form.password}}
<input type="submit" id="submit" name="submit" value="Sign in" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
forgot username/password<br />
new user
</body>
</html>
my problem is, the template doesn't appear to be getting passed any of the context it's supposed to. In the rendered HTML, all of my variable tags simply disappear (i.e. rather than being replaced by the appropriate values, thay are replaced with nothing).
I imagine I'm skipping some critical step, but I can't figure out what it is. Any ideas?
You need to change from 'template' to 'template_name'
urlpatterns=patterns('django.contrib.auth.views',
url(r'^/$','login',{'template_name':'mytemplate.html'}),
https://docs.djangoproject.com/en/1.4/topics/auth/#django.contrib.auth.views.login
Try removing the template name from your url configuration. Django will then fall back to a standard template, that way you can see if you screwed up the template somehow or if something else is wrong.
My next guess would be to check your settings for the TEMPLATE_CONTEXT_PROCESSORS. If you have defined any of them, be sure to include
"django.contrib.auth.context_processors.auth",
If you haven't defined any, django will use a standard tuple, which allready includes the auth processor.