mailgun and flask forms - flask

I keep getting the following error when I run my code:
TypeError: 'Response' object is not callable
Here is my code...
from flask import Flask, render_template, flash
import os
import requests
import forms
app = Flask(__name__)
app.secret_key = 'jfdsjajfjds'
mg_key = os.environ['MAILGUN_API_KEY']
#app.route("/", methods=('GET', 'POST'))
def landing():
form = forms.OptinForm()
if form.validate_on_submit():
return requests.post(
"https://api.mailgun.net/v3/lists/test_list#sandbox.mailgun.org/members",
auth=('api', 'mg_key'),
data={'subscribed': True,
'address': form.email.data,
'name': form.first_name.data})
flash("Thanks! Check your email.")
return render_template('landing.html', form=form)
if __name__ == "__main__":
app.run()

I figured out the problem. I was calling my API key variable as a string. fixed it by changing 'mg_key' to mg_key

Related

Internal servor error response from the flask application

Hello i am writing the following code to authenticate the username and password and execute a entry method code if the given credentials are valid. But i am getting internal server error.Can someone help where it is getting wrong. My target is to execute a block of code if the credentials are matching.
#import statements
import Example
import Example2
import logging
from flask import Flask
from flask_httpauth import HTTPBasicAuth
from werkzeug.security import generate_password_hash, check_password_hash
#Creating the logge r variables and intialization
log=logging.getLogger()
format = "%(asctime)s %(message)s"
logging.basicConfig(format=format, level=logging.INFO, filename='Job_history_logs.log')
#Starting the Flask application
app = Flask(__name__)
auth = HTTPBasicAuth()
#users
users = {
"john": generate_password_hash("hello"),
"susan": generate_password_hash("bye")
}
#app.route('/todo/api/v1.0/tasks', methods=['GET'])
#auth.login_required
#auth.verify_password
def verify_password(username, password):
log.info("Username provided is "+ str(username))
log.info("password provided is "+ str(password))
if username in users:
log.info("Hash comparision is "+ str(check_password_hash(users.get(username), password)))
if check_password_hash(users.get(username), password):
return True
#auth.error_handler
def unauthorized():
return make_response(jsonify({'error': 'Unauthorized access'}), 401)
def entry():
result1 = Example.external()
result2 = Example2.external2()
log.info("result1 is "+str(result1))
log.info(str(result2))
return str(result1)+"...."+str(result2)
if __name__ == '__main__':
app.run(host='0.0.0.0')
I was able to run this application with simple changes in the sequence of usage of #auth_decorators.
working code
#import statements
import logging
from external import star_matrix
from flask_httpauth import HTTPBasicAuth
from flask import Flask
from werkzeug.security import generate_password_hash, check_password_hash
#Creating an object
log=logging.getLogger()
format = "%(asctime)s %(message)s"
logging.basicConfig(format=format, level=logging.INFO, filename='Job_history_logs.log')
app = Flask(__name__)
auth = HTTPBasicAuth()
#users
users = {
"john": generate_password_hash("hello"),
"susan": generate_password_hash("bye")
}
#auth.verify_password
def verify_password(username, password ):
log.info("Username provided is "+ str(username))
log.info("password provided is "+ str(password))
if username in users:
log.info("Hash comparision is "+ str(check_password_hash(users.get(username), password)))
if check_password_hash(users.get(username), password):
return True
#app.route('/todo/api/v1.0/tasks', methods=['GET'])
#auth.login_required
def entry():
log.info('inside the entry function')
result = star_matrix.external()
return result
if __name__ == '__main__':
app.run(host='0.0.0.0')

Importing flask-socketio instance from a top level file?

I have a run.py file at the top level of my directory where I initialize flask-socketio. That file looks like this:
# /run.py
#!/usr/bin/env python
import os
from src.config import app_config
from dotenv import load_dotenv, find_dotenv
from flask_socketio import SocketIO
from src.app import create_app
load_dotenv(find_dotenv())
env_name = os.getenv('FLASK_ENV')
app = create_app(env_name)
socketio = SocketIO(app, async_mode=None)
if __name__ == '__main__':
port = os.getenv('PORT')
# run app
socketio.run(app, host='0.0.0.0', port=port)
My app.py file sits under src/app.py and looks like this:
def create_app(env_name):
"""
Create app
"""
# app initiliazation
app = Flask(__name__)
app.config.from_object(app_config[env_name])
# initializing bcrypt and db
bcrypt.init_app(app)
db.init_app(app)
app.register_blueprint(message_blueprint, url_prefix='/api/v1/message')
return app
I am trying to import the socketio instance into /src/views/MessageView.py
My MessageView.py file looks like this:
from ..models import db
from __main__ import socketio
from ..shared.Authentication import Auth
from threading import Lock
from flask import Flask, render_template, session, request, \
copy_current_request_context, g, Blueprint, json, Response
from flask_socketio import SocketIO, emit, join_room, leave_room, \
close_room, rooms, disconnect
message_api = Blueprint('message_api', __name__)
thread = None
thread_lock = Lock()
def background_thread():
"""Example of how to send server generated events to clients."""
count = 0
while True:
socketio.sleep(10)
count += 1
socketio.emit('my_response',
{'data': 'Server generated event', 'count': count},
namespace='/test')
#message_api.route('/')
def index():
return render_template('index.html', async_mode=socketio.async_mode)
#socketio.on('my_event', namespace='/test')
def test_message(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']})
#socketio.on('my_broadcast_event', namespace='/test')
def test_broadcast_message(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']},
broadcast=True)
#socketio.on('join', namespace='/test')
def join(message):
join_room(message['room'])
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': 'In rooms: ' + ', '.join(rooms()),
'count': session['receive_count']})
#socketio.on('leave', namespace='/test')
def leave(message):
leave_room(message['room'])
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': 'In rooms: ' + ', '.join(rooms()),
'count': session['receive_count']})
#socketio.on('close_room', namespace='/test')
def close(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response', {'data': 'Room ' + message['room'] + ' is closing.',
'count': session['receive_count']},
room=message['room'])
close_room(message['room'])
#socketio.on('my_room_event', namespace='/test')
def send_room_message(message):
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': message['data'], 'count': session['receive_count']},
room=message['room'])
#socketio.on('disconnect_request', namespace='/test')
def disconnect_request():
#copy_current_request_context
def can_disconnect():
disconnect()
session['receive_count'] = session.get('receive_count', 0) + 1
# for this emit we use a callback function
# when the callback function is invoked we know that the message has been
# received and it is safe to disconnect
emit('my_response',
{'data': 'Disconnected!', 'count': session['receive_count']},
callback=can_disconnect)
#socketio.on('my_ping', namespace='/test')
def ping_pong():
emit('my_pong')
#socketio.on('connect', namespace='/test')
def test_connect():
global thread
with thread_lock:
if thread is None:
thread = socketio.start_background_task(background_thread)
emit('my_response', {'data': 'Connected', 'count': 0})
#socketio.on('disconnect', namespace='/test')
def test_disconnect():
print('Client disconnected', request.sid)
I have spent the last two days scouring the internet for help on how to fix this. The error i receive is:
ImportError: cannot import name 'socketio'
I have tried relative imports as well as monkey_patching. But each time the error still occurs. Any ideas on how to fix the issue would be greatly appreciated.
P.S. I am adapting the example that Miguel has in his flask-socketio repo located here: link. In his example, everything sits in one file, which would work in a basic app, however, for an app with 50+ API endpoints, that is not an optimal solution.
Why do you have the SocketIO object in the top-level run.py module? Since this is a Flask extension, it is better to have it with all your other extensions in src/app.py:
from flask_socketio import SocketIO
socketio = SocketIO()
def create_app(env_name):
"""
Create app
"""
# app initiliazation
app = Flask(__name__)
app.config.from_object(app_config[env_name])
# initializing bcrypt and db
bcrypt.init_app(app)
db.init_app(app)
# initialize socketio
socketio.init_app(app)
app.register_blueprint(message_blueprint, url_prefix='/api/v1/message')
return app
Then in run.py you can import this object:
from src.app import create_app, socketio
# ...
env_name = os.getenv('FLASK_ENV')
app = create_app(env_name)
# ...
if __name__ == '__main__':
port = os.getenv('PORT')
# run app
socketio.run(app, host='0.0.0.0', port=port)
And in the same way you can import it in your MessageView.py module:
from src.app import socketio
socketio.on('whatever')
def do_something(data):
pass
I have a complete example application that uses this structure here: https://github.com/miguelgrinberg/Flask-SocketIO-Chat.

How to have scrapy spider run on flask app form submit?

I'm setting up a flask app that will allow me to input a string and it will pass that string argument to my spider to webscrape a page. I'm having difficulty getting the spider to run on the press of a form submit(integrating scrapy&flask).
I've looked at the following code snippet solutions to no avail:
Run Scrapy from Flask,
Running Scrapy spiders in a Celery task,
Scrapy and celery `update_state`
It definitely appears that there are different ways to complete the task. However - each of the code snippets above does not appear to be working.
routes.py
from flask import render_template, flash, redirect, url_for, session, jsonify
from flask import request
from flask_login import login_required
from flask_login import logout_user
from app import app, db
from app.forms import LoginForm
from flask_login import current_user, login_user
from app.models import User
from werkzeug.urls import url_parse
from app.forms import RegistrationForm, SearchForm
#from app.tasks import scrape_async_job
import pprint
import requests
import json
#app.route('/')
#app.route('/index', methods=['GET','POST'])
#login_required
def index():
jobvisuals = [
{
'Job': 'Example',
'Desc': 'This job requires a degree...',
'link': 'fakelink',
'salary': '10$/hr',
'applied': 'Boolean',
'interview': 'Boolean'}]
params = {
'spider_name': 'Indeedspider',
'start_requests': True
}
response = requests.get('http://localhost:9080/crawl.json', params).json()
data = response
pprint.pprint(data)
form = SearchForm()
if request.method == 'GET':
return render_template('index.html', title='home', jobvisuals=jobvisuals, form=form, search=session.get('search',''))
job_find = request.form['search']
session['search'] = job_find
if form.validate_on_submit():
print('Working on this feature :D')
flash('Searching for job {}').format(form.search.data)
return render_template('index.html', title='Home', jobvisuals=jobvisuals, form=form)
spider
import scrapy
class IndeedSpider(scrapy.Spider):
name = 'indeedspider'
allowed_domains = ['indeed.com']
def __init__(self, job='', **kwargs):
self.start_url('http://www.indeed.com/jobs?q={job}&l=San+Marcos%2C+CA')
super().__init__(**kwargs)
def parse(self, response):
for item in response.xpath("//div[contains(#class,'jobsearch-SerpJobCard unifiedRow row result clickcard')]").getall():
yield {
'title': item.xpath("//div[contains(#class,'title')]/text()").get(default='None'),
'desc': item.xpath("//div[contains(#class,'summary')]/text()").get(default='None'),
'link': item.xpath("//div[contains(#class,'title')]/#href").get(default='None'),
'location': item.xpath("//span[contains(#class,'location')]/text()").get(default='None'),
'salary': item.xpath("//div[contains(#class,'salarySnippet')]/text()").get(default='None')
}
Expected:
I type in a input box the job, job gets passed to spider on submit, spider scrapes indeed.com and pulls the first page only and returns that data on the index page.
Actual:
Unsure of where to start.
Can anyone point me in the right direction?

Custom error handler in flask_restful throws NameError

I am trying to add a custom error code to a flask_restful API, following the directions given in the docs however I do not receive the correct response and I am getting a NameError: global name 'UnsupportedMediaType' is not defined message. What am I doing wrong here?
# -*- coding: utf-8 -*-
from flask import Flask, request
from flask_restful import Resource, Api
import service
errors = {
'UnsupportedMediaType': {
'message': 'Unsupported Media Type',
'status': 415
}
}
app = Flask(__name__)
api = Api(app, errors=errors)
class Service(Resource):
def post(self):
if request.is_json:
data = request.get_json()
return service.handler(args['data'])
else:
raise UnsupportedMediaType
api.add_resource(Service, '/')
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
You must store the error handler to a function. Like this:
def error(exception):
return {some json error data with the message 'exception'}
now you can call the error handler as you want.
OR
You can use Flask error handler decorator for that. Heres the link

python flask mini-application global name not defined

I keep getting the error NameError: global name 'NameForm' is not defined
Here is my views.py
from flask import Flask, render_template
from flask_bootstrap import Bootstrap
from app import forms
app = Flask(__name__)
bootstrap = Bootstrap(app)
#app.route('/', methods=['GET', 'POST'])
def index():
name = None
form = NameForm()
if form.validate_on_submit():
name = form.name.data
form.name.data = ''
return render_template('index.html', form=form, name=name)
if __name__ == '__main__':
app.run(debug=True)
And here is my forms.py
from flask_wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required
class NameForm(Form):
"""docstring for ClassName"""
name = StringField('Your name please', validators=[Required()])
submit = SubmitField('Submit')
Any ideas on what i might be doing wrong???