I have some common question about http get vs post,It would be great if someone can clarify with examples...
Examples:-
Here is my view
views.py
def search(request):
if request.method == 'POST':
print 'request.post=', request.POST
print 'request.get=', request.GET
print 'request.method=', request.META.get('REQUEST_METHOD')
if 'q' in request.GET:
message = 'You searched for :%r' % request.POST['q']
else:
message = 'You submitted an empty form'
return render(request, 'search_form.html', {'message': message})
return render(request, 'search_form.html')
search_form.html
<body>
{% if message %}
<div> {{ message }} </div>
{% else %}
<form action="/polls/search/" method="post">{% csrf_token %}
<input type="text" name="q">
<input type="submit" value="Search">
</form>
{% endif %}
</body>
Will POST request used only with the HTML forms? If not, what are the other ways to do it?
Any request without a form is always a GET request?
How to handle GET and POST using a form..
Thanks.
Will POST request used only with the HTML forms? If not, what are the
other ways to do it?
You can post json or xml too. For example, Jquery uses ajax post of json or xml data type
Any request without a form is always a GET request?
There are 4 types of http methods, GET,POST, DELETE and PUT. Depending on how you want to use it, you can use any of them.
An article more on this. http://bradley-holt.com/2009/07/html-5-http-methods-rest/
.
Related
I have the following code and I'm submitting a form. When I hit the submit button, my form validation prints out False. I've checked and made sure I'm including everything from different posts, but I can't get it to validate. Is there anything I'm doing wrong?
#app.route('/index.html', methods=['GET', 'POST'])
def index():
user = {'nickname': 'Rafa'}
form = FilterForm()
print("about to validate", file=sys.stderr)
if form.validate_on_submit():
print("validated", file=sys.stderr)
filters_array = form.filter.split(',')
streaming(filters_array)
response = {"response", "yes"}
redirect("/authenticate")
return render_template('index.html',
title="Home",
user=user,
form=form)
class FilterForm(Form):
filter = StringField('filter', validators=[DataRequired()])
Here is my Jinja file
{% block content %}
<h1> I have successfully navigated to the title pagee </h1>
<h1> Hello, {{user.nickname}}!</h1>
<h1> Get Tweets </h1>
<p> Please enter a comma delimited list of filters</p>
<form action="" method="post" name="login">
{{form.filter(size=80)}}
<input type="submit" value="Get Tweets!">
</form>
{% endblock %}
FilterForm should not be indented at the same level as def index(). More importantly, you don't have a csrf_token in your form. Which will prevent it from validating.
Add this to your form:
{{ form.csrf_token }}
Lastly, when validating with wtforms, the errors are populated in the form object. So after an if validate, try printing form.errors and you'll find out exactly what is wrong.
Another requirement is that when you use form.validate_on_submit, you have to make sure that you had use all fields of your form model.
I have found some syntax error in your code, maybe that will cause the problem you have met.
first, the problem in your decorator app.route:
app.route('/index')
second, in your html file:
form action='/index'
I have apparently forgotten something really basic about django. Here's my views.py:
def sourcedoc_create(request):
if request.method == 'POST': # If the form has been submitted...
form = SourcedocForm(request.POST, request.FILES) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
handle_uploaded_file(request.FILES['doc'])
form.save()
return HttpResponseRedirect('/index/') # Redirect after POST
else:
form = SourcedocForm() # An unbound form
return render_to_response(
'sourcedoc_create.html',
{'form': form},
RequestContext(request)
Here's the relevant part of urls.py:
url(r'^$', index),
url(r'^index/', index),
url(r'^sourcedoc/create/', sourcedoc_create),
When I run the app, I create the record in the database, and the uploaded file appears successfully in the relevant directory (thus I infer that the form.save worked ok), but then I get:
KeyError at /sourcedoc/create/
0
Request Method: POST
Request URL: http://www.rosshartshorn.net/worldmaker/sourcedoc/create/
Django Version: 1.4.3
It appears that my HttpResponseRedirect is, for whatever reason, not working, and it's trying to re-POST and throwing a KeyError off a blank form? Or something. In any event, it's not redirecting. When I manually go to /index/, all is well, and the new record is there.
Any ideas what is wrong with my redirect?
In case the forms are relevant:
<body>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<h1>New Post</h1>
<form enctype="multipart/form-data" action="" method="post">
<table>
{{ form.as_table }}
</table>
{% csrf_token %}
<input type="submit" value="Submit">
</form>
Also, I'm using mongoforms, which is supposed to work like ModelForms:
from mongodbforms import DocumentForm
class SourcedocForm(DocumentForm):
class Meta:
document = Sourcedoc
It seems to have been at least somewhat related to this post: Django MongodbForms KeyError _meta['cascade'].
So, I just upgraded to Django 1.5 and the newest mongodbforms. This eliminated that error, although I was then getting a problem similar to this:
MongoKit "ImportError: No module named objectid " error
I just implemented keppla's answer from that second post, and it now seems to work!
I am quite new to django and struggling to do something very simple.
I have a ModelForm for the following model:
class Queries(models.Model):
user_id=models.CharField(max_length=200)
query=models.CharField(max_length=200)
And I am showing the user a simple form that will help in doing the following:
user will ask a question
The question will be processed(a database query will be generated
based on the question)
Then the query result should be shown just beneath the form in the
same page.
This is how my views.py looks like:
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from basicapp.models import QueryForm
def index(request):
form=MyForm()
real_form=form.getForm(request)
response=form.response
return render(request,'basicapp/index.html',{
'form': real_form,
'response':response,
})
class MyForm:
response=''
def getForm(self,request):
form = QueryForm(request.POST)
if form.is_valid():
response=form.cleaned_data['query']
form.save()
return form
For now I am trying simple stuffs,I am taking the value in query field of the form and trying to send it back to the page;so far I am failed.
This is index.html:
<form action=" " method="post">{% csrf_token %}
{{ form }}
<p>{{response}}</p>
<input type="submit" value="Submit" />
</form>
If I could do this,I think the query stuffs wont be that tough.The form is working fine,the datas are getting saved in database. Only the response string from views.py could not be retrieved inside index.html after form submission. Can you please help?
EDIT:
Tried following in index.html based on Hoff's answer:
<form id="myForm" action=" " method="get">{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
<div id="response">
</div>
<script language="JavaScript">
$(document).ready(function() {
$("#myForm").submit(function() { // catch the form's submit event
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // get the form data
type: $(this).attr('GET'),
success: function(response) { // on success..
$("#response").html(response); // update the DIV
}
});
return false;
});
});
</script>
Still no luck :(
views.py
def index(request):
questions=None
if request.GET.get('search'):
search = request.GET.get('search')
questions = Queries.objects.filter(query__icontains=search)
name = request.GET.get('name')
query = Queries.object.create(query=search, user_id=name)
query.save()
return render(request, 'basicapp/index.html',{
'questions': questions,
})
html
<form method="GET">
Question: <input type="text" name="search"><br/>
Name: <input type="text" name="name"><br/>
<input type="submit" value="Submit" />
</form><br/><br/>
{% for question in questions %}
<p>{{question}}</p>
{% endfor %}
What you need is an asynchronous post (ajax), which is easy with jQuery, see this answer for a complete solution: How to POST a django form with AJAX & jQuery
<input type="text" name="query" />
<input type="submit" name="submit" value="Submit" />
you can check if the form was submitted or not (i.e if it's a post request or not):
if 'submit' in request.POST: #you could use 'query' instead of 'submit' too
# do post related task
# add context variables to render post output
# add another context variable to indicate if it's a post
# Example:
context.update({'post_output': request.POST.get('query','')})
...
return render(request, 'index.html', context)
Then in the template, check if context variable post_output exists, if it does show the output:
{% if post_output %}
Output: {{ post_output }}
{% endif %}
In short, the logic is:
Check if a relevant request.POST dict key exists or not in your view.
If the key exists, then it's a post request; add post related context variables and do post related tasks.
Check if any post related context variable is available in the template and if it does, show post related output.
If you don't want to show the output when the page is simply refreshed after a post, pass the request object to the template and do a check like this:
{% if request.POST.submit and post_output %}
Following Hoff's answer...
Add URL attribute to ajax call:
$(document).ready(function() {
$("#myForm").submit(function() { // catch the form's submit event
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // get the form data
type: $(this).attr('GET'),
url: '/URL-to-ajax-view/',
success: function(response) { // on success..
$("#response").html(response); // update the DIV
}
});
return false;
});
});
Some ajax handler in views.py:
# /URL-to-ajax-view/
def ajax_get_response(request):
if request.method == "GET" and request.is_ajax:
form = QueryForm(request.POST or None)
if form.is_valid():
form.save()
return HttpResponse(form.response)
raise Http404
Tried something like that?
I have a form like so:
class MyForm(forms.Form):
site = forms.ChoiceField(choices=SITE_CHOICES, label=ugettext_lazy('Site'),)
...
params = forms.MultipleChoiceField(
choices=PARAM_CHOICES,
label=ugettext_lazy('Select Parameters'),
widget=forms.CheckboxSelectMultiple()
)
And in my template:
<form action="{% url results %}" method="get">{% csrf_token %}
{% for field in myform %}
<div class="field_wrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<input type="submit" name="submit" value="{% trans 'Query' %}" />
</form>
My problem is that when I submit the form as GET the variables are like the following:
site=1¶ms=foo¶ms=bar¶ms=something&submit=Query
my params variable is clearly being overwritten by the last choice? How can get access to the submitted data as separate variables?
Any help appreciated.
Using Django forms
You should be using Django's form handling with a POST which would majke things easier. Here goes:
if request.method == 'GET':
form = MyFormClass()
else:
form = MyFormClass(request.POST)
if form.is_valid():
do_something_with(form.cleaned_data['params'])
return redirect('somewhere')
return render_to_response('my_template.html', RequestContext(request, {'form':form}))
Notes on using GET vs POST with forms
It's useless to include {% csrf_token %} if you're going to GET the form (Absolutely no csrf validation is done with GET requests, which make sense, as GET requests are supposed to be non-data-altering.
Anyway, if you're really going to GET the page, you can still use the same logic as written before, with a little tuning:
form = MyFormClass(request.GET)
if form.is_valid():
do_something_with(form.cleaned_data['params'])
return render_to_response('some_template.html', {'stuff':some_stuff})
return render_to_response('form_submission_page.html', {'form':form})
Last thing, using GET to submit data is usually bad practice, unless you're creating some search function or altering display (pagination & all).
Using request.GET
Now, if for some reason you don't want to use Django forms, you can still get around the problem and retrieve your params, you simply need to use the QueryDict.getlist instead of using the QueryDict.get method.
Here goes:
my_data = request.GET.getlist('params')
Documentation
Don't forget to check out the Django documentation on QueryDicts and on forms
And use {% csrf_token %} in get request is a bad practice.
Use form.is_valid() and form.cleaned_data['params'].
I have a form which allows users to select several parameters to allow faceted querying of data. As there is no data entry going on here I want the form to post to GET and I have a another view with a different template which displays the results.
I want the form to validate as normal so that if a required field is not completed the corresponding errors are displayed. At the moment my process looks like this (simplified):
my search view:
def search(request):
...
context['form'] = GraphForm()
...
return render(request, 'search.html', context)
my results view:
def results(request):
if 'submit' in request.GET:
# process GET variables as query
...
return render(request, 'results.html', context)
my search.html template:
<form action="{% url results %}" method="get">{% csrf_token %}
{% for field in form %}
<div class="field_wrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
<input type="submit" name="submit" value="Query" />
</form>
Given that the form submits to another url with separate view code, what is the best way to go about validating (highlighting errors), and ensuring I have my GET data?
Any help much appreciated.
This might be a little late, but I think the following will work while maintaining similarity to 'POST' workflow:
Instead of having two different views for searching and displaying results, just have one view. The normal codepath described for post forms can then be followed. Instead of using request.method == 'POST' to detect form submission, we instead use 'submit' in request.GET. If using javascript to submit the form, make sure that 'submit' is included in the GET data or use a hidden field to detect form submission.
views.py
def search(request):
context_dict = {}
if 'submit' in request.GET:
form = GraphForm(request.GET)
if form.is_valid():
#do search and add results to context
#If you don't want to use a single view,
# you would redirect to results view here.
results = get_results(**form.cleaned_date)
context_dict['results'] = results
else:
form = GraphForm()
context_dict['form'] = form
return render(request, 'search.html', context_dict)
search.html
<form action="{% url 'search' %}" method="get">
{{form}}
<input type="submit" name="submit" value="Query" />
</form>
{% if results %}
{% include 'results.html' %}
{% endif %}
You should be able to pass request.GET just like request.POST to the form. The form simply accepts a data dictionary. It doesn't care where that comes from. Have you already tried that?
Use JavaScript/jQuery for form validation. All you need to do is add an id to form, and in the corresponding Javascript, do something like
document.getElementById("#form").onsubmit = checkForm();
or using jQuery
$("#form").submit(checkForm);
where checkForm() returns true upon successful validation, and false otherwise. (Note that, if you do not return false, form submission will continue as usual.)
Which fields you check for/validate can also change by using Django's templates.