Czy ktoś wie, dlaczego nie mogę zastąpić istniejącej funkcji punktu końcowego, jeśli mam dwie takie reguły adresu URL
app.add_url_rule('/',
view_func=Main.as_view('main'),
methods=["GET"])
app.add_url_rule('/<page>/',
view_func=Main.as_view('main'),
methods=["GET"])
Śledzenie:
Traceback (most recent call last):
File "demo.py", line 20, in <module> methods=["GET"])
File ".../python2.6/site-packages/flask/app.py",
line 62, in wrapper_func return f(self, *args, **kwargs)
File ".../python2.6/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: main
Odpowiedzi:
Nazwy widoków muszą być unikalne, nawet jeśli wskazują na tę samą metodę widoku.
app.add_url_rule('/', view_func=Main.as_view('main'), methods = ['GET']) app.add_url_rule('/<page>/', view_func=Main.as_view('page'), methods = ['GET'])
źródło
.as_view($VIEW_NAME)
wywołanie metody $ VIEW_NAME in powinno być przekazane jako unikalna nazwa ciągu.Ten sam problem przytrafił mi się, gdy miałem więcej niż jedną funkcję API w module i próbowałem opakować każdą funkcję dwoma dekoratorami:
Dostałem ten sam wyjątek, ponieważ próbowałem zawinąć więcej niż jedną funkcję tymi dwoma dekoratorami:
@app.route("/path1") @exception_handler def func1(): pass @app.route("/path2") @exception_handler def func2(): pass
W szczególności jest to spowodowane próbą zarejestrowania kilku funkcji z opakowaniem nazwy :
def exception_handler(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: error_code = getattr(e, "code", 500) logger.exception("Service exception: %s", e) r = dict_to_json({"message": e.message, "matches": e.message, "error_code": error_code}) return Response(r, status=error_code, mimetype='application/json') return wrapper
Zmiana nazwy funkcji rozwiązała to za mnie ( wrapper .__ name__ = func .__ name__ ):
def exception_handler(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: error_code = getattr(e, "code", 500) logger.exception("Service exception: %s", e) r = dict_to_json({"message": e.message, "matches": e.message, "error_code": error_code}) return Response(r, status=error_code, mimetype='application/json') # Renaming the function name: wrapper.__name__ = func.__name__ return wrapper
Następnie udekorowano więcej niż jeden punkt końcowy.
źródło
functools.wraps
do zmiany nazwy funkcji.wrapper.__name__
zamiastwrapper.func_name
. Być może jest to różnica między pythonem2 a pythonem3?wrapper.__name__ = func.__name__
przed wywołaniem wrappera rozwiązało problem.W przypadku użytkowników, którzy używają @ app.route, lepiej jest użyć klucza-argumentu
endpoint
, niż zmienić wartość,__name__
jak stwierdził Roei Bahumi . Na jego przykładzie będzie:@app.route("/path1", endpoint='func1') @exception_handler def func1(): pass @app.route("/path2", endpoint='func2') @exception_handler def func2(): pass
źródło
Flask wymaga powiązania pojedynczej „funkcji widoku” z „punktem końcowym”. Dzwonisz
Main.as_view('main')
dwa razy, co tworzy dwie różne funkcje (dokładnie ta sama funkcjonalność, ale inna w sygnaturze pamięci). Krótka historia, po prostu powinieneś to zrobićmain_view_func = Main.as_view('main') app.add_url_rule('/', view_func=main_view_func, methods=["GET"]) app.add_url_rule('/<page>/', view_func=main_view_func, methods=["GET"])
źródło
Chciałbym tylko dodać do tego rozwiązanie bardziej „szablonowe”.
def func_name(f): def wrap(*args, **kwargs): if condition: pass else: whatever you want return f(*args, **kwargs) wrap.__name__ = f.__name__ return wrap
chciałbym tylko dodać naprawdę ciekawy artykuł „Demystifying Decorators”, który niedawno znalazłem: https://sumit-ghosh.com/articles/demystifying-decorators-python/
źródło
Może się to również zdarzyć, gdy masz identyczne nazwy funkcji na różnych trasach.
źródło
Jeśli uważasz, że masz unikalne nazwy punktów końcowych, a nadal jest podawany ten błąd, prawdopodobnie masz problem . Tak samo było ze mną.
Ten problem dotyczy kolby 0.10, jeśli masz tę samą wersję, a następnie wykonaj następujące czynności, aby się tego pozbyć:
sudo pip uninstall flask sudo pip install flask=0.9
źródło
Istnieje poprawka dotycząca problemu z Flask # 570 wprowadzonego niedawno (flask 0.10), który powoduje zgłoszenie tego wyjątku.
Zobacz https://github.com/mitsuhiko/flask/issues/796
Więc jeśli przejdziesz do flask / app.py i zakomentujesz 4 linie 948..951, może to pomóc, dopóki problem nie zostanie w pełni rozwiązany w nowej wersji.
Różnica tej zmiany jest tutaj: http://github.com/mitsuhiko/flask/commit/661ee54bc2bc1ea0763ac9c226f8e14bb0beb5b1
źródło
Nazwy twoich widoków muszą być unikalne, nawet jeśli wskazują na tę samą metodę widoku, lub możesz dodać z functools import wraps i użyć @wraps https://docs.python.org/2/library/functools.html
źródło
użyj flask 0.9 zamiast tego użyj następujących poleceń
sudo pip uninstall flask
sudo pip install flask==0.9
źródło
Dodanie
@wraps(f)
powyżej funkcji opakowania rozwiązało mój problem.def list_ownership(f): @wraps(f) def decorator(*args,**kwargs): return f(args,kwargs) return decorator
źródło