Background:
Using urllib and urllib2 in Python, you can do a form submission.
You first create a dictionary.
formdictionary = { 'search' : 'stackoverflow' }
Then you use urlencode method of urllib to transform this dictionary.
params = urllib.urlencode(formdictionary)
You can now make a url request with urllib2 and pass the variable params as a secondary parameter with the first parameter being the url.
open = urllib2.urlopen('www.searchpage.com', params)
From my understanding, urlencode automatically encodes the dictionary in html and adds the input tag. It takes the key to be the name attribute. It takes value in the dictionary to be the value of the name attribute. Urllib2 send this html code via an HTTP POST request.
Problem:
This is alright if the html code you are submitting to is formatted in a standard way with the html tag input having the name attribute.
<input id="32324" type="text" name="search" >
But, there is the situation where the html code is not properly formatted. And the html input tag only has an id attribute no name attribute. Is there may be another way to access the input tag via the id attribute? Or is there may be yet another way?
Solution:
?
According to the W3 standard, for an input field to be submitted, it must have a name attribute. A quick test on Firefox 3 and Safari 3.2 shows that an input field that is missing the name attribute but has an id attribute is not submitted.
With that said, if you have a form that you want to submit, and some of its fields have id but not name attributes, using the id attribute instead seems like the only available option. It could be that other browsers use the id attribute, or perhaps there is some JavaScript code that handles the submission event instead of letting the browser do it.
An input tag without a name won't be submitted as a form parameter.
For example, create an HTML page containing just this:
<form>
<input type="text" name="one" value="foo"/>
<input type="text" value="bar"/>
<input type="submit"/>
</form>
You can see that the second text field is missing a name attribute. If you click "Submit," the page will refresh with the query string:
test.html?one=foo
A good strategy for this would be to look at a live POST request sent by your browser and start by emulating that. Use a tool like the FireBug extension for Firefox to see the POST request and parameters sent by your browser. There might be parameters in there that you didn't notice before -- possibly because they were hidden form elements or they were created/set by JavaScript.
Related
I'm trying to update a database value called ''favorites'' for the logged in user of a Flask web app using a button click. Essentially, the favorites column is a single string that looks like this: Apples, Bananas, Oranges where on the button click, I would want to append a value (say Cherries) by breaking apart the string into a list in my #app.routes(), appending the value, and rejoining it back into a string before committing the changes. I'm not sure what the proper way is to do this, here's what I have:
HTML snippet
<button action="{{ url_for('add') }}" method="post" type="submit">Favorite</button>
#app.routes()
#app.route('/add', methods=['POST'])
def add():
star_faves = current_user.favorites
star_faves_list = star_faves.split(', ')
star_faves_list.append('Cherries')
', '.join(star_faves_list)
current_user.favorites = star_faves_list
db.session.commit()
return render_template('add.html')
The problem is that I don't really understand how the HTML is communicating with Python/Jinja, if anybody can help clear that up I would greatly appreciate it.
It looks like you have some elements confused.
If you want to submit a POST request to the /add page, the easiest way is to create a form. (Buttons do not have an action or method attribute, forms do.) When you create the form, you also specify the HTTP method to use when submitting the form. So in your case, it should look something like this:
<form action="{{ url_for('add') }}" method="POST">
<input type="submit" value="Favorite">
</form>
You can use a button instead of an input with type submit, they are interchangeable.
If you don't want the page to reload while submitting the request, a more advanced technique you can use with JavaScript is something called AJAX.
This example code sends the same POST request to the /add page:
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
// this method gets called if the state of the request changes (it succeeds of fails)
// you will probably want to update your page accordingly here
};
request.open('POST', '/add');
request.send();
I'm having a tough time figuring out how to parse my URL GET data and send it to the right view.
I have a search view that only has a search input:
template/search.html
<form action="http://domain.com/schools/search/" method="GET" >
<input type="text" name = "q_word">
<input type="submit" value="Search"/>
</form>
When a user enters in a search term, I want to send that data to another view to parse and use in a geocoding function I wrote. Here is a look at my urls.py:
url(r'^schools/search/$', school_views.find_school, name="find_school"),
url(r'^schools/search/(?P<address>[\w ]+)$', school_views.geo_locate, name="geo_locate"),
I want to grab the GET data from a URL (after they've entered in the info), and pass it as an address argument to my school_views.geo_locate function.
This set up works great when you manually type out a URL like: schools/search/150%20main%20Street
But when a user submits any form data, the URL passed is /schools/search/?q_word=150+west+main and I'm just kicked back to my search template.
I think my regex needs to be tweaked in my second url argument, but I just keep returning to the search page after submission, with no data going to my geo_locate view. Is this a URLs problem?
GET data is not passed in the URL parameters. Don't try to capture it in the regex. Just get it from request.GET inside the view.
My form submits as follows
<form class="form-signin" role="form" action="{% provider_login_url "facebook" method="js_sdk" next="/next"%}">
I overrode the DefaultAccountAdapter with my own AccountAdapter with method
def get_login_redirect_url(self, request):
print request.GET['next']
...
But request loses the next parameter and the print returns an error because there is no "next" in request.GET.
Why can't I access the next parameter?
I was originally using get_login_redirect_url to handle different url redirects after creation of social versus username/password users. Now, I need to be able to specific the next parameter in the URL for another variant of behavior for social user login but am unable to access the next parameter because it does not seem to be passed.
I am not sure whether I could give the precise solution for your issue. But I think got the point.
To access the next parameter from url,
The url should be,
http://127.0.0.1:8000/index?next=2
If you have to form the url in this above manner,you can get access to the next argument from request object in your corresponding view method
print request.GET.get('next')
So, please make sure to format request url with proper querystring refer
To your case,
I have no idea about {% provider_login_url %} template tag
I am assuming after your tag rendered it yields the url index, then i am appending my querystring next
<form class="form-signin" role="form" action="/index?next=someValue">
you may try additionally,
{% provider_login_url "facebook" next=next %}
source
I came across with a similar problem. However, I wasn't signing in with facebook. request.GET was always empty.
I think you could try using jQuery to manually append next parameter to the action attribute of <form>. See this question. It solves my problem.
i like to use the url template tag in my model's content.
example:
models content:
Car.description = 'this is a link to our main page: home'
in template.html:
<div>{{ Car.description }}</div>
result
<div>this is a link to our main page: home
is it possible, or do i have to write my own template tag?
thanks in advance
Roman
Assuming you have this:
car.description = 'this is a link to our main page: home'
You can do:
from django.template import Context, Template
from django.core.urlresolvers import reverse
class Car(models.Model):
def description_with_url(self):
return Template(self.description).render({'url': reverse('home')})
or use the same logic in custom template tag instead of method..
I can't figure out why you would need to do that. Assuming that I fully-understood your question, you are attempting to store something within a model's field that then behaves "dynamically" when rendered.
A model field's content that stores a URL should contain a URL and only a URL by utilizing the URLField.
Else, if you're dynamically building the URL from somewhere else, simply use template markup, i.e. the url template tag as it is meant to be used; it can also take parameters depending on the specific URL pattern. I.e. the url tag is meant to be used in the template's context.
Let me know if you update the question to describe what you are trying to achieve. But storing "behaviour" at data level is something to simply stay away from.
Trying to use Python mechanize to log in to a webpage. Since I have a problem with finding the correct form, instead of posting the URL (which the code might change) I will copy some of the code here for future users. I read this, but there didn't seem too be a definitive answer.
Anyways, I did everything with mechanize in this tutorial up until where I am getting the forms.
When I call:
for form in br.forms():
print form
I get back:
POST https://www.myexample.com/x-www-form-urlencoded
HiddenControl(utf8=✓) (readonly)
HiddenControl(authenticity_token=BfqPL1ilOXeg08Or/CEBAiK4duWgncY=
CheckboxControl(affiliate[remember_me]=[1])
Looking at the raw HTML I see:
<label for="affiliate_email">Email<./label>
<.input autofocus="autofocus" id="affiliate_email"
name="affiliate[email]" size="30" type="email" />
However, when I try to select the email field I get a form not found error.
br.select_form(name="affiliate[email]")
# updated to
br.select_form(nr=0)
# Now what do I do here to enter something into that form?
br.form['someIDhere']='myEmail#example.com'
I have also tried using the form ID, and many other possible form names. I don't understand why printing the forms with br.forms() returns those strange results, does this mean the site is using javascript for login forms?
Thank you in advance!
affiliate[email] is not the name of a form, but of an input within the form.
Try using:
br.select_form(nr=0)
if the form has no name and is the first/only form on the page.