Flask exception "View function mapping is overwriting an existing endpoint function" - python

I'm following this book called: "Flask web development".
When I'm creating the login system he creates then I can an exception at my registration of the blueprint I have made.
Log:
C:\Python27\python.exe "C:/Users/Bo/Google Drev/Privat/HobbyProjekter/Event/manage.py"
Traceback (most recent call last):
File "C:/Users/Bo/Google Drev/Privat/HobbyProjekter/Event/manage.py", line 7, in <module>
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
File "C:\Users\Bo\Google Drev\Privat\HobbyProjekter\Event\app\__init__.py", line 42, in create_app
app.register_blueprint(auth_blueprint, url_prefix='/auth')
File "C:\Python27\lib\site-packages\flask\app.py", line 62, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Python27\lib\site-packages\flask\app.py", line 889, in register_blueprint
blueprint.register(self, options, first_registration)
File "C:\Python27\lib\site-packages\flask\blueprints.py", line 153, in register
deferred(state)
File "C:\Python27\lib\site-packages\flask\blueprints.py", line 172, in <lambda>
s.add_url_rule(rule, endpoint, view_func, **options))
File "C:\Python27\lib\site-packages\flask\blueprints.py", line 76, in add_url_rule
view_func, defaults=defaults, **options)
File "C:\Python27\lib\site-packages\flask\app.py", line 62, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Python27\lib\site-packages\flask\app.py", line 984, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: auth.login
The code for where I register my blueprint looks like this:
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')
And that code imports from my auth__init__.py :
from flask import Blueprint
auth = Blueprint('auth', __name__)
from . import views
from flask import render_template
from . import auth
#auth.route('/login')
def login():
return render_template('auth/login.html')
At last my view I'm trying to register (just a snippet):
#auth.route('/login', methods=['GET', 'POST'])
def login():
Hope you can help

You have 2 endpoints called '/login'. Change one of their names. Also the functions can't have the same names either.

Related

How to debug patched method with unittest.mock

I have the following (simplified) FBV:
def check_existing_contacts(request):
if request.is_ajax and request.method == "GET":
print('Function called')
return mailgun_validate_email(request)
return JsonResponse({"error": "Incorrect AJAX / GET request."}, status=400)
I want to test that the mailgun_validate_email function is called:
class TestCheckExistingContacts(TestCase):
#patch('myapp.mailgun_validate_email')
def test_new_contact(self, mock):
client = Client()
client.get('/check/', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertTrue(mock.called)
I am certain the test calls mailgun_validate_email as the print('Function called') displays in the console. However I get an assertion error that the mock.called is False.
Where am I going wrong / how can I debug this?
************ UPDATE *******************
When patching the function in the same module as the view, I get the following error:
class TestCheckExistingContacts(TestCase):
#patch('[path to views.py with check_existing_contacts].mailgun_validate_email')
def test_new_contact(self, mock):
client = Client()
client.get('/check/', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertTrue(mock.called)
Results in:
Failure
Traceback (most recent call last):
File "\tests\test_utils.py", line 123, in test_new_contact
response = self.client.get('/validate/',
File "\.venv\lib\site-packages\django\test\client.py", line 518, in get
response = super().get(path, data=data, secure=secure, **extra)
File "\.venv\lib\site-packages\django\test\client.py", line 344, in get
return self.generic('GET', path, secure=secure, **{
File "\.venv\lib\site-packages\django\test\client.py", line 421, in generic
return self.request(**r)
File "\.venv\lib\site-packages\django\test\client.py", line 496, in request
raise exc_value
File "\.venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "\.venv\lib\site-packages\django\utils\deprecation.py", line 96, in __call__
response = self.process_response(request, response)
File "\.venv\lib\site-packages\django\contrib\sessions\middleware.py", line 45, in process_response
patch_vary_headers(response, ('Cookie',))
File "\.venv\lib\site-packages\django\utils\cache.py", line 267, in patch_vary_headers
vary_headers = cc_delim_re.split(response['Vary'])
TypeError: expected string or bytes-like object
If you did from myapp import mailgun_validate_email for check_existing_contacts, then you need to patch the reference in that module instead of myapp.
E.g. if the import is in myapp/views.py, then patch myapp.views.mailgun_validate_email.
The view needs to return an instance of HttpResponse or one of its subclasses, same for mailgun_validate_email since you directly return mailgun_validate_email(...).
# #patch('myapp.mailgun_validate_email') # Change this
#patch('myapp.views.mailgun_validate_email', return_value=JsonResponse({})) # to this

Error while building a RESTApi using flask_restful

Flask RESTApi newbie here
I am trying to build a RESTapi service in Flask (and I am trying to save the output as a .txt file) using flask_restful for a code of mine using the pydifact module as follows:
import datetime
from pydifact.message import Message
from pydifact.segments import Segment
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class RestAPI(Resource):
def get(self, ABSENDER_ID, EMPFÄNGER_ID, ERSTELLUNG_DATUM_ZEIT, REFERENCE):
MSCONS = Message()
def erstellung_datum_zeit(dt_time):
# Needed for the UNB segment
dt_time = dt_time.strftime('%Y%m%d%H%M')
return dt_time
def UNA_UNB_segment(absender_id, empfänger_id, erst_datum, ref):
MSCONS.add_segment(Segment('UNA', ":+.? '"))
MSCONS.add_segment(Segment('UNB', ['UNOC', '3'], [absender_id, '14'], [
empfänger_id, '500'], [erst_datum[2:8], erst_datum[8:]], ref, '', 'TL'))
ERSTELLUNG_DATUM_ZEIT = str(
erstellung_datum_zeit(datetime.datetime.now()))
UNA_UNB_segment(ABSENDER_ID, EMPFÄNGER_ID,
ERSTELLUNG_DATUM_ZEIT, REFERENCE)
result = MSCONS.serialize()
final_result = result
PATH_FOR_TXT = r'C:\Users\kashy\OneDrive\Desktop\Codes\mscons.txt'
textfile = open(PATH_FOR_TXT, 'w')
textfile.write(result)
textfile.close()
return {'result': final_result}
api.add_resource(
RestAPI,
'/RestAPI/<int:ABSENDER_ID>/<int:EMPFÄNGER_ID/<int:ERSTELLUNG_DATUM_ZEIT/<int:REFERENCE>')
if __name__ == '__main__':
app.run(debug=True)
The ABSENDER_ID, EMPFÄNGER_ID, ERSTELLUNG_DATUM_ZEIT, REFERENCE should all be user inputs and they should be all in string format.
When I do /RestAPI/<str:ABSENDER_ID>/<str:EMPFÄNGER_ID/<str:ERSTELLUNG_DATUM_ZEIT/<str:REFERENCE>, i get the following error:
C:\Users\kashy\OneDrive\Desktop\Codes\pydifact> & C:/Users/kashy/Anaconda3/envs/py36/python.exe c:/Users/kashy/OneDrive/Desktop/Codes/api.py
Traceback (most recent call last):
File "c:/Users/kashy/OneDrive/Desktop/Codes/api.py", line 44, in <module>
self.url_map.add(rule)
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 1401, in add
rule.bind(self)
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 730, in bind
self.compile()
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 790, in compile
_build_regex(self.rule if self.is_leaf else self.rule.rstrip("/"))
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 779, in _build_regex
convobj = self.get_converter(variable, converter, c_args, c_kwargs)
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 738, in get_converter
raise LookupError("the converter %r does not exist" % converter_name)
LookupError: the converter 'str' does not exist
and when I do
/RestAPI/<int:ABSENDER_ID>/<int:EMPFÄNGER_ID/<int:ERSTELLUNG_DATUM_ZEIT/<int:REFERENCE>, I get the following error:
PS C:\Users\kashy\OneDrive\Desktop\Codes\pydifact> & C:/Users/kashy/Anaconda3/envs/py36/python.exe c:/Users/kashy/OneDrive/Desktop/Codes/api.py
Traceback (most recent call last):
File "c:/Users/kashy/OneDrive/Desktop/Codes/api.py", line 44, in <module>
'/RestAPI/<int:ABSENDER_ID>/<int:EMPFÄNGER_ID/<int:ERSTELLUNG_DATUM_ZEIT/<int:REFERENCE>')
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\flask_restful\__init__.py", line 382, in add_resource
self._register_view(self.app, resource, *urls, **kwargs)
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\flask_restful\__init__.py", line 448, in _register_view
app.add_url_rule(rule, view_func=resource_func, **kwargs)
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\flask\app.py", line 98, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\flask\app.py", line 1277, in add_url_rule
self.url_map.add(rule)
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 1401, in add
rule.bind(self)
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 730, in bind
self.compile()
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 790, in compile
_build_regex(self.rule if self.is_leaf else self.rule.rstrip("/"))
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 766, in _build_regex
for converter, arguments, variable in parse_rule(rule):
File "C:\Users\kashy\Anaconda3\envs\py36\lib\site-packages\werkzeug\routing.py", line 226, in parse_rule
raise ValueError("malformed url rule: %r" % rule)
ValueError: malformed url rule: '/RestAPI/<int:ABSENDER_ID>/<int:EMPFÄNGER_ID/<int:ERSTELLUNG_DATUM_ZEIT/<int:REFERENCE>'
I am totally new to this and just started learning it using the Building a REST API using Python and Flask | Flask-RESTful tutorial.
Can anyone please tell me what is the mistake I am doing?
Your url routes have problem. In the first one, it should be string instead of str and in the second one you have a missing > at the end of int:EMPFÄNGER_ID and int:ERSTELLUNG_DATUM_ZEIT
Correct ones should be:
/RestAPI/<string:ABSENDER_ID>/<string:EMPFANGER_ID>/<string:ERSTELLUNG_DATUM_ZEIT>/<string:REFERENCE>
and
/RestAPI/<int:ABSENDER_ID>/<int:EMPFANGER_ID>/<int:ERSTELLUNG_DATUM_ZEIT>/<int:REFERENCE>
Note: I replaced Ä with A in urls above because that might also cause malformed url rule issue.

Setting Jinja environment global variable outside of request context

I have a function called generate_csrf_token which is located in package commons.formsecurity containing the following code.
import random
import string
from flask import session
def generate_csrf_token():
if '_csrf_token' not in session:
state = ''.join(random.choice(string.ascii_uppercase + string.digits)
for x in xrange(32))
session['_csrf_token'] = state
return session['_csrf_token']
I am calling this in my create_app function.
from flask import Flask
from routes_manager import configure_blueprints
from error_handling import configure_error_handling
from flask import session
from flask.ext.session import Session
from commons.formsecurity import generate_csrf_token
def create_app():
"""Create the Flask App"""
app = Flask(__name__)
app.secret_key = 'lalalalalala'
app.jinja_env.globals['csrf_token'] = generate_csrf_token()
configure_blueprints(app)
configure_error_handling(app)
return app
create_app is called from main.py
from app import create_app
app = create_app()
"""Run the clients"""
if __name__ == '__main__':
app.run(debug=True)
When I run my Flask application. I get the following error.
ERROR 2017-05-25 12:12:50,720 wsgi.py:263]
Traceback (most recent call last):
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 240, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 299, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 85, in LoadObject
obj = __import__(path[0])
File "C:\Code\App-Engine\cfc-melbourne-website\main.py", line 3, in <module>
app = create_app()
File "C:\Code\App-Engine\cfc-melbourne-website\app\__init__.py", line 12, in create_app
app.jinja_env.globals['csrf_token'] = generate_csrf_token()
File "C:\Code\App-Engine\cfc-melbourne-website\app\commons\formsecurity.py", line 7, in generate_csrf_token
if '_csrf_token' not in session:
File "lib\werkzeug\local.py", line 379, in <lambda>
__contains__ = lambda x, i: i in x._get_current_object()
File "lib\werkzeug\local.py", line 306, in _get_current_object
return self.__local()
File "lib\flask\globals.py", line 37, in _lookup_req_object
raise RuntimeError(_request_ctx_err_msg)
RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.
Where is the best place to call the following
app.jinja_env.globals['csrf_token'] = generate_csrf_token()
If you don't call the generate_csrf_token() function, and instead store the reference to the function, you can call it in your Jinja templates (which will be in the context where a request is available).
So replace
app.jinja_env.globals['csrf_token'] = generate_csrf_token()
With
app.jinja_env.globals['csrf_token'] = generate_csrf_token
And in your templates, use:
<input name=_csrf_token type=hidden value="{{ csrf_token() }}">

TypeError: __init__() got an unexpected keyword argument 'method'

Well, I am writing a Flask project, but when I tried to python manage.py
The traceback told me that:
Traceback (most recent call last):
File "manage.py", line 5, in <module>
from app import db,create_app
File "/home/humbert/2017-sharing-backend/sharing/app/__init__.py", line 42, in <module>
app.register_blueprint(main_blueprint, url_prefix='/main')
File "/home/humbert/venv/local/lib/python2.7/site-packages/flask/app.py", line 64, in wrapper_func
return f(self, *args, **kwargs)
File "/home/humbert/venv/local/lib/python2.7/site-packages/flask/app.py", line 951, in register_blueprint
blueprint.register(self, options, first_registration)
File "/home/humbert/venv/local/lib/python2.7/site-packages/flask/blueprints.py", line 154, in register
deferred(state)
File "/home/humbert/venv/local/lib/python2.7/site-packages/flask/blueprints.py", line 173, in <lambda>
s.add_url_rule(rule, endpoint, view_func, **options))
File "/home/humbert/venv/local/lib/python2.7/site-packages/flask/blueprints.py", line 76, in add_url_rule
view_func, defaults=defaults, **options)
File "/home/humbert/venv/local/lib/python2.7/site-packages/flask/app.py", line 64, in wrapper_func
return f(self, *args, **kwargs)
File "/home/humbert/venv/local/lib/python2.7/site-packages/flask/app.py", line 1043, in add_url_rule
rule = self.url_rule_class(rule, methods=methods, **options)
TypeError: __init__() got an unexpected keyword argument 'method'
I think my manage.py is right,and I can't figure out the mistake.
The mistake part of __init__.py is that:
from .main import main as main_blueprint
app.register_blueprint(main_blueprint, url_prefix='/main')
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix="/auth")
from . import views
I really need some help, thanks!
I had a similar problem. In my code I had a line
#bp.route('/<init:id>/delete', method=('POST'))
The keyword method needs to be changed to methods(with an s)
I had encountered a similar problem in my code and just had to change the keyword "method" to "methods":
#app.route('/login', methods = ['GET', 'POST'])

View function mapping is overwriting an existing endpoint function when using a decorator

I am using the decorator below to authenticate endpoints in my application.
from google.appengine.api import users
from flask import redirect, render_template, request
from google.appengine.ext import ndb
def authenticate_admin(func):
def authenticate_and_call(*args, **kwargs):
user = users.get_current_user()
if user is None:
return redirect(users.create_login_url(request.url))
else:
email = user.email()
register_user_if_required(email, user)
if not users.is_current_user_admin():
return redirect_to_unauthorized(email)
return func(*args, **kwargs)
def redirect_to_unauthorized(email):
return render_template('xxxx/vvvv.html',
email=email,
users=users)
return authenticate_and_call
def register_user_if_required(email, user):
I have the following endpoint which only allows administrators to access it.
#admin_routes.route('/xxxx')
#authenticate_admin
def xxxxx():
return render_template('xxxx/xxxxx.html',
user=user,
logout=users.create_logout_url('/'))
And it works in the sense that only administrator's can access the above endpoint. However when I try to add a new endpoint with the same annotation but a different fancy url I get an error. Here is the code for the endpoint.
#admin_routes.route('/xxxx/bbbbbb')
#authenticate_admin
def abc():
.....
return render_template('xxxx/xxxx/zzzzz.html',
user=user,
breadcrumb=breadcrumb)
And here is the error I get when I run my app.
Traceback (most recent call last):
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 240, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 299, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/wsgi.py", line 85, in LoadObject
obj = __import__(path[0])
File "/Users/vinay/App-Engine/xxxxx/main.py", line 61, in <module>
app.register_blueprint(admin_routes)
File "/Users/vinay/App-Engine/xxxxx/server/lib/flask/app.py", line 62, in wrapper_func
return f(self, *args, **kwargs)
File "/Users/vinay/App-Engine/xxxxx/server/lib/flask/app.py", line 889, in register_blueprint
blueprint.register(self, options, first_registration)
File "/Users/vinay/App-Engine/xxxxx/server/lib/flask/blueprints.py", line 153, in register
deferred(state)
File "/Users/vinay/App-Engine/xxxxx/server/lib/flask/blueprints.py", line 172, in <lambda>
s.add_url_rule(rule, endpoint, view_func, **options))
File "/Users/vinay/App-Engine/xxxxx/server/lib/flask/blueprints.py", line 76, in add_url_rule
view_func, defaults=defaults, **options)
File "/Users/vinay/App-Engine/xxxxx/server/lib/flask/app.py", line 62, in wrapper_func
return f(self, *args, **kwargs)
File "/Users/vinay/App-Engine/xxxxx/server/lib/flask/app.py", line 984, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: admin_routes.authenticate_and_call
Traceback (most recent call last):
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ereporter/ereporter.py", line 240, in emit
record.exc_info)
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/datastore.py", line 2520, in RunInTransactionCustomRetries
return RunInTransactionOptions(options, function, *args, **kwargs)
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/datastore.py", line 2630, in RunInTransactionOptions
ok, result = _DoOneTry(function, args, kwargs)
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/datastore.py", line 2650, in _DoOneTry
result = function(*args, **kwargs)
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ereporter/ereporter.py", line 270, in __EmitTx
handler=self.__RelativePath(os.environ['PATH_TRANSLATED']))
File "/Users/vinay/Desktop/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/runtime/request_environment.py", line 113, in __getitem__
return self._request.environ[key]
KeyError: 'PATH_TRANSLATED'
Logged from file wsgi.py, line 263
INFO 2015-08-09 03:19:14,731 module.py:812] default: "GET / HTTP/1.1" 500 -
You need to ensure your decorator wrapper has the same name as the wrapped view function, otherwise all your views look like the same endpoint (authenticate_and_call).
You can do so with the #functool.wraps() utility:
from functools import wraps
def authenticate_admin(func):
#wraps(func)
def authenticate_and_call(*args, **kwargs):
user = users.get_current_user()
if user is None:
return redirect(users.create_login_url(request.url))
else:
email = user.email()
register_user_if_required(email, user)
if not users.is_current_user_admin():
return redirect_to_unauthorized(email)
return func(*args, **kwargs)
def redirect_to_unauthorized(email):
return render_template('Admin/UnauthorizedAdmin.html',
email=email,
users=users)
return authenticate_and_call
This ensures that metadata such as the function name is copied over from func to the authenticate_and_call wrapper. From there on out #Flask.route() can pick up that name to use as the endpoint name.

Categories