Reputation: 1432
I'm building a rather simple CRM using the Flask Python framework. I have a database of companies that we are interested in contacting. The user first inputs how many companies they would like to contact. The user is then redirected to this page:
Essentially for each row/company on this page, the user will click either the contact or don't contact radio button.
What I am trying to accomplish
Once the user clicks the 'Let the Magic Happen' button at the bottom, JavaScript runs through each row and sees which button is clicked. It then appends the database unique ID to one of two arrays, 'contact' and 'remove'. This information then gets passed along to python via getJSON, python captures the json data using request.args.get.
Finally, Python does one of two things:
Where I am getting hung up
I can't seem to retrieve the json data in Python, I am trying to just do a simple print statement as of right now to show that I can pull in the data.
Also, would it be more efficient in terms of performance to have the javascript send each row to python individually or all at once in an array?
Scripts
app.py
@app.route('/send_emails')
def send_emails():
contact = request.args.get('contact')
remove = request.args.get('remove')
print contact
print remove
return ('', 204) #No need to return anything
email.js
$('#batch-page .magic-button').click( function() {
//Iterate over each company row
$('#batch-page table tr.company-row').each(function(i, company){
company = $(company);
company_id = company.attr('class').split(' ')[1];
//Assign arrays for emailing and removing comapnies
var contact = [];
var remove = [];
//Check to see whether the contact or don't contact checkbox is checked
if(company.children('td.contact-company').children('input').is(':checked')) {
contact.push(company_id);
} else if (company.children('td.remove-company').children('input').is(':checked')) {
remove.push(company_id);
}
//Pass the data along to Python
$.getJSON('/send_emails', {
contact: contact,
remove: remove
});
});
$('div#batch-page').html('<p>Be patient, contacting companies!</p>');
});
batch.html
{% for company in companies %}
<tr class="company-row {{ company.id }}">
<td class="company-name">
<p>{{ company.company_name }}</p>
</td>
<td class="company-website">
<div>
<a href="{{ company.website }}" target="blank_">{{ company.website }}</a>
</div>
</td>
<td class="company-email">
<p>{{ company.email_address }}</p>
</td>
<td class="contact-company">
<input type="checkbox" class="contact" for='{{ company.id }}'>
</td>
<td class="remove-company">
<input type="checkbox" class="dont-contact" for='{{ company.id }}'></td>
<td>
<a class="btn btn-primary" data-toggle="collapse" data-target="#{{ company.id }}-info">Change Company Information</a>
</td>
</tr>
<tr class="company-info-row">
<td colspan="6" class="hiddenRow">
<div class="accordion-body collapse" id="{{ company.id }}-info">
<form action="" id="{{ company.id }}-edit-form" method="POST" class="update-company-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<div class="col-md-4">
<div class="form-group">
<label for="{{ company.id }}-company-name">Company Name</label>
<input type="text" value="{{ company.company_name }}" id="{{ company.id }}-company-name" class="form-control" name="company-name">
<label for="{{ company.id }}-company-website">Company Website</label>
<input type="text" value="{{ company.website }}" id="{{ company.id }}-company-website" class="form-control" name="company-website">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="{{ company.id }}-email-address">Company Email</label>
<input type="text" value="{{ company.email_address }}" id="{{ company.id }}-email-address" class="form-control" name="company-email">
</div>
<div class="form-group">
<input type="submit" form="{{ company.id }}-edit-form" class="btn btn-default" value="Update">
</div>
</div>
<div class="col-md-4 ajax-message">
<div>
<i class="fa fa-clock-o fa-2x"></i>
<p style="display: inline-block;">Date scraped on: {{ company.scraped_on }}</p>
</div>
</div>
</form>
</div>
</td>
</tr>
{% endfor %}
Update #1
Tried using the loads method from the json module to load in the request, I am getting the following error message:
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/wyssuser/Desktop/dscraper/app.py", line 82, in send_emails
content = json.loads(request.json)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 338, in loads
return _default_decoder.decode(s)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 365, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: expected string or buffer
Upvotes: 2
Views: 4187
Reputation: 59
There is a typo: contacts = request.args.getList('contact')
. I think you would have written contacts = request.args.getlist('contact')
.
Upvotes: -1
Reputation: 3515
First of all jQuery.getJSON()
issues a GET request using the JSON object you pass it as query parameters.
The problem here is that jQuery.getJSON()
serializes the lists in a non traditional way. So if you looked at the request received sent by the browser it would look something like:
http://example.com/?contact[]=me&contact[]=others&contact[]=hr&remove[]=you&remove[]=doug
Now, Flask will parse that querystring into an args dict that has the keys contact[]
and remove[]
but since you're doing `request.args.get('contact'), you get nothing
The solution is to create the query parameters yourself before passing to jQuery.getJSON()
like this. This can be done using jQuery.param()
:
//Assign arrays for emailing and removing companies
var contact = ["me", "others", "hr"];
var remove = ["you", "doug"];
//Pass the data along to Python
$.getJSON(
'/send_emails',
$.param({ contact: contact, remove: remove }, true)
);
Note the true
passed to jQuery.param()
, it returns the querystring in the traditional format which looks like this:
contact=me&contact=others&contact=hr&remove=you&remove=doug
Now, you can retrieve your parameters in Flask using
contacts = request.args.getList('contact')
print(contacts) # ['me', 'others', 'hr']
Upvotes: 3
Reputation: 137
you need to get the json from the request,
content = request.json
Then using your favorite json parser parse the json into an object.
obj = json.loads(content)
To answer your question, "would it be more efficient in terms of performance to have the javascript send each row to python individually or all at once in an array?", it would be more efficient to send all of the data at once and return one return.
Upvotes: 1